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
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import fnmatch
|
|
5
|
+
import locale
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
import sphinx.locale
|
|
12
|
+
from sphinx import __display_version__
|
|
13
|
+
from sphinx.cmd.quickstart import EXTENSIONS
|
|
14
|
+
from sphinx.ext.apidoc._generate import create_modules_toc_file, recurse_tree
|
|
15
|
+
from sphinx.ext.apidoc._shared import LOGGER, ApidocOptions, _remove_old_files
|
|
16
|
+
from sphinx.locale import __
|
|
17
|
+
from sphinx.util.osutil import ensuredir
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from collections.abc import Sequence
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_parser() -> argparse.ArgumentParser:
|
|
25
|
+
parser = argparse.ArgumentParser(
|
|
26
|
+
usage='%(prog)s [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH> [EXCLUDE_PATTERN, ...]',
|
|
27
|
+
epilog=__('For more information, visit <https://www.sphinx-doc.org/>.'),
|
|
28
|
+
description=__("""
|
|
29
|
+
Look recursively in <MODULE_PATH> for Python modules and packages and create
|
|
30
|
+
one reST file with automodule directives per package in the <OUTPUT_PATH>.
|
|
31
|
+
|
|
32
|
+
The <EXCLUDE_PATTERN>s can be file and/or directory patterns that will be
|
|
33
|
+
excluded from generation.
|
|
34
|
+
|
|
35
|
+
Note: By default this script will not overwrite already created files."""),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
parser.add_argument(
|
|
39
|
+
'--version',
|
|
40
|
+
action='version',
|
|
41
|
+
dest='show_version',
|
|
42
|
+
version=f'%(prog)s {__display_version__}',
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
parser.add_argument('module_path', help=__('path to module to document'))
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
'exclude_pattern',
|
|
48
|
+
nargs='*',
|
|
49
|
+
help=__(
|
|
50
|
+
'fnmatch-style file and/or directory patterns to exclude from generation'
|
|
51
|
+
),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
'-o',
|
|
56
|
+
'--output-dir',
|
|
57
|
+
action='store',
|
|
58
|
+
dest='dest_dir',
|
|
59
|
+
required=True,
|
|
60
|
+
help=__('directory to place all output'),
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
'-q',
|
|
64
|
+
action='store_true',
|
|
65
|
+
dest='quiet',
|
|
66
|
+
help=__('no output on stdout, just warnings on stderr'),
|
|
67
|
+
)
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
'-d',
|
|
70
|
+
'--maxdepth',
|
|
71
|
+
action='store',
|
|
72
|
+
dest='max_depth',
|
|
73
|
+
type=int,
|
|
74
|
+
default=4,
|
|
75
|
+
help=__('maximum depth of submodules to show in the TOC (default: 4)'),
|
|
76
|
+
)
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
'-f',
|
|
79
|
+
'--force',
|
|
80
|
+
action='store_true',
|
|
81
|
+
dest='force',
|
|
82
|
+
help=__('overwrite existing files'),
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
'-l',
|
|
86
|
+
'--follow-links',
|
|
87
|
+
action='store_true',
|
|
88
|
+
dest='follow_links',
|
|
89
|
+
default=False,
|
|
90
|
+
help=__(
|
|
91
|
+
'follow symbolic links. Powerful when combined with collective.recipe.omelette.'
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
'-n',
|
|
96
|
+
'--dry-run',
|
|
97
|
+
action='store_true',
|
|
98
|
+
dest='dry_run',
|
|
99
|
+
help=__('run the script without creating files'),
|
|
100
|
+
)
|
|
101
|
+
parser.add_argument(
|
|
102
|
+
'-e',
|
|
103
|
+
'--separate',
|
|
104
|
+
action='store_true',
|
|
105
|
+
dest='separate_modules',
|
|
106
|
+
help=__('put documentation for each module on its own page'),
|
|
107
|
+
)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
'-P',
|
|
110
|
+
'--private',
|
|
111
|
+
action='store_true',
|
|
112
|
+
dest='include_private',
|
|
113
|
+
help=__('include "_private" modules'),
|
|
114
|
+
)
|
|
115
|
+
parser.add_argument(
|
|
116
|
+
'--tocfile',
|
|
117
|
+
action='store',
|
|
118
|
+
dest='toc_file',
|
|
119
|
+
default='modules',
|
|
120
|
+
help=__('filename of table of contents (default: modules)'),
|
|
121
|
+
)
|
|
122
|
+
parser.add_argument(
|
|
123
|
+
'-T',
|
|
124
|
+
'--no-toc',
|
|
125
|
+
action='store_false',
|
|
126
|
+
dest='toc_file',
|
|
127
|
+
help=__("don't create a table of contents file"),
|
|
128
|
+
)
|
|
129
|
+
parser.add_argument(
|
|
130
|
+
'-E',
|
|
131
|
+
'--no-headings',
|
|
132
|
+
action='store_true',
|
|
133
|
+
dest='no_headings',
|
|
134
|
+
help=__(
|
|
135
|
+
"don't create headings for the module/package "
|
|
136
|
+
'packages (e.g. when the docstrings already '
|
|
137
|
+
'contain them)'
|
|
138
|
+
),
|
|
139
|
+
)
|
|
140
|
+
parser.add_argument(
|
|
141
|
+
'-M',
|
|
142
|
+
'--module-first',
|
|
143
|
+
action='store_true',
|
|
144
|
+
dest='module_first',
|
|
145
|
+
help=__('put module documentation before submodule documentation'),
|
|
146
|
+
)
|
|
147
|
+
parser.add_argument(
|
|
148
|
+
'--implicit-namespaces',
|
|
149
|
+
action='store_true',
|
|
150
|
+
dest='implicit_namespaces',
|
|
151
|
+
help=__(
|
|
152
|
+
'interpret module paths according to PEP-0420 implicit namespaces specification'
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
parser.add_argument(
|
|
156
|
+
'--automodule-options',
|
|
157
|
+
dest='automodule_options',
|
|
158
|
+
default='',
|
|
159
|
+
help=__(
|
|
160
|
+
'Comma-separated list of options to pass to automodule directive '
|
|
161
|
+
'(or use SPHINX_APIDOC_OPTIONS).'
|
|
162
|
+
),
|
|
163
|
+
)
|
|
164
|
+
parser.add_argument(
|
|
165
|
+
'-s',
|
|
166
|
+
'--suffix',
|
|
167
|
+
action='store',
|
|
168
|
+
dest='suffix',
|
|
169
|
+
default='rst',
|
|
170
|
+
help=__('file suffix (default: rst)'),
|
|
171
|
+
)
|
|
172
|
+
exclusive_group = parser.add_mutually_exclusive_group()
|
|
173
|
+
exclusive_group.add_argument(
|
|
174
|
+
'--remove-old',
|
|
175
|
+
action='store_true',
|
|
176
|
+
dest='remove_old',
|
|
177
|
+
help=__(
|
|
178
|
+
'Remove existing files in the output directory that were not generated'
|
|
179
|
+
),
|
|
180
|
+
)
|
|
181
|
+
exclusive_group.add_argument(
|
|
182
|
+
'-F',
|
|
183
|
+
'--full',
|
|
184
|
+
action='store_true',
|
|
185
|
+
dest='full',
|
|
186
|
+
help=__('generate a full project with sphinx-quickstart'),
|
|
187
|
+
)
|
|
188
|
+
parser.add_argument(
|
|
189
|
+
'-a',
|
|
190
|
+
'--append-syspath',
|
|
191
|
+
action='store_true',
|
|
192
|
+
dest='append_syspath',
|
|
193
|
+
help=__('append module_path to sys.path, used when --full is given'),
|
|
194
|
+
)
|
|
195
|
+
parser.add_argument(
|
|
196
|
+
'-H',
|
|
197
|
+
'--doc-project',
|
|
198
|
+
action='store',
|
|
199
|
+
dest='header',
|
|
200
|
+
help=__('project name (default: root module name)'),
|
|
201
|
+
)
|
|
202
|
+
parser.add_argument(
|
|
203
|
+
'-A',
|
|
204
|
+
'--doc-author',
|
|
205
|
+
action='store',
|
|
206
|
+
dest='author',
|
|
207
|
+
help=__('project author(s), used when --full is given'),
|
|
208
|
+
)
|
|
209
|
+
parser.add_argument(
|
|
210
|
+
'-V',
|
|
211
|
+
'--doc-version',
|
|
212
|
+
action='store',
|
|
213
|
+
dest='version',
|
|
214
|
+
help=__('project version, used when --full is given'),
|
|
215
|
+
)
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
'-R',
|
|
218
|
+
'--doc-release',
|
|
219
|
+
action='store',
|
|
220
|
+
dest='release',
|
|
221
|
+
help=__(
|
|
222
|
+
'project release, used when --full is given, defaults to --doc-version'
|
|
223
|
+
),
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
group = parser.add_argument_group(__('extension options'))
|
|
227
|
+
group.add_argument(
|
|
228
|
+
'--extensions',
|
|
229
|
+
metavar='EXTENSIONS',
|
|
230
|
+
dest='extensions',
|
|
231
|
+
action='append',
|
|
232
|
+
help=__('enable arbitrary extensions, used when --full is given'),
|
|
233
|
+
)
|
|
234
|
+
for ext in EXTENSIONS:
|
|
235
|
+
group.add_argument(
|
|
236
|
+
f'--ext-{ext}',
|
|
237
|
+
action='append_const',
|
|
238
|
+
const=f'sphinx.ext.{ext}',
|
|
239
|
+
dest='extensions',
|
|
240
|
+
help=__('enable %s extension, used when --full is given') % ext,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
group = parser.add_argument_group(__('Project templating'))
|
|
244
|
+
group.add_argument(
|
|
245
|
+
'-t',
|
|
246
|
+
'--templatedir',
|
|
247
|
+
metavar='TEMPLATEDIR',
|
|
248
|
+
dest='template_dir',
|
|
249
|
+
help=__('template directory for template files'),
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
return parser
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def main(argv: Sequence[str] = (), /) -> int:
|
|
256
|
+
"""Run the apidoc CLI."""
|
|
257
|
+
locale.setlocale(locale.LC_ALL, '')
|
|
258
|
+
sphinx.locale.init_console()
|
|
259
|
+
|
|
260
|
+
opts = _parse_args(argv)
|
|
261
|
+
rootpath = opts.module_path
|
|
262
|
+
excludes = tuple(
|
|
263
|
+
re.compile(fnmatch.translate(str(Path(exclude).resolve())))
|
|
264
|
+
for exclude in dict.fromkeys(opts.exclude_pattern)
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
written_files, modules = recurse_tree(rootpath, excludes, opts, opts.template_dir)
|
|
268
|
+
|
|
269
|
+
if opts.full:
|
|
270
|
+
_full_quickstart(opts, modules=modules)
|
|
271
|
+
elif opts.toc_file:
|
|
272
|
+
written_files.append(
|
|
273
|
+
create_modules_toc_file(modules, opts, opts.toc_file, opts.template_dir)
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
if opts.remove_old and not opts.dry_run:
|
|
277
|
+
_remove_old_files(written_files, opts.dest_dir, opts.suffix)
|
|
278
|
+
|
|
279
|
+
return 0
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _parse_args(argv: Sequence[str], /) -> ApidocOptions:
|
|
283
|
+
parser = get_parser()
|
|
284
|
+
args = parser.parse_args(argv or sys.argv[1:])
|
|
285
|
+
|
|
286
|
+
# normalise options
|
|
287
|
+
|
|
288
|
+
args.module_path = root_path = Path(args.module_path).resolve()
|
|
289
|
+
args.dest_dir = Path(args.dest_dir)
|
|
290
|
+
if not root_path.is_dir():
|
|
291
|
+
LOGGER.error(__('%s is not a directory.'), root_path)
|
|
292
|
+
raise SystemExit(1)
|
|
293
|
+
|
|
294
|
+
if args.header is None:
|
|
295
|
+
args.header = root_path.name
|
|
296
|
+
args.suffix = args.suffix.removeprefix('.')
|
|
297
|
+
|
|
298
|
+
if not args.dry_run:
|
|
299
|
+
ensuredir(args.dest_dir)
|
|
300
|
+
|
|
301
|
+
if not args.automodule_options:
|
|
302
|
+
args.automodule_options = frozenset()
|
|
303
|
+
elif isinstance(args.automodule_options, str):
|
|
304
|
+
args.automodule_options = frozenset(args.automodule_options.split(','))
|
|
305
|
+
|
|
306
|
+
return ApidocOptions(**args.__dict__)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _full_quickstart(opts: ApidocOptions, /, *, modules: list[str]) -> None:
|
|
310
|
+
from sphinx.cmd import quickstart as qs
|
|
311
|
+
|
|
312
|
+
modules.sort()
|
|
313
|
+
prev_module = ''
|
|
314
|
+
text = ''
|
|
315
|
+
for module in modules:
|
|
316
|
+
if module.startswith(prev_module + '.'):
|
|
317
|
+
continue
|
|
318
|
+
prev_module = module
|
|
319
|
+
text += f' {module}\n'
|
|
320
|
+
d: dict[str, Any] = {
|
|
321
|
+
'path': str(opts.dest_dir),
|
|
322
|
+
'sep': False,
|
|
323
|
+
'dot': '_',
|
|
324
|
+
'project': opts.header,
|
|
325
|
+
'author': opts.author or 'Author',
|
|
326
|
+
'version': opts.version or '',
|
|
327
|
+
'release': opts.release or opts.version or '',
|
|
328
|
+
'suffix': '.' + opts.suffix,
|
|
329
|
+
'master': 'index',
|
|
330
|
+
'epub': True,
|
|
331
|
+
'extensions': [
|
|
332
|
+
'sphinx.ext.autodoc',
|
|
333
|
+
'sphinx.ext.viewcode',
|
|
334
|
+
'sphinx.ext.todo',
|
|
335
|
+
],
|
|
336
|
+
'makefile': True,
|
|
337
|
+
'batchfile': True,
|
|
338
|
+
'make_mode': True,
|
|
339
|
+
'mastertocmaxdepth': opts.max_depth,
|
|
340
|
+
'mastertoctree': text,
|
|
341
|
+
'language': 'en',
|
|
342
|
+
'module_path': str(opts.module_path),
|
|
343
|
+
'append_syspath': opts.append_syspath,
|
|
344
|
+
}
|
|
345
|
+
if opts.extensions:
|
|
346
|
+
d['extensions'].extend(opts.extensions)
|
|
347
|
+
if opts.quiet:
|
|
348
|
+
d['quiet'] = True
|
|
349
|
+
|
|
350
|
+
for ext in d['extensions'][:]:
|
|
351
|
+
if ',' in ext:
|
|
352
|
+
d['extensions'].remove(ext)
|
|
353
|
+
d['extensions'].extend(ext.split(','))
|
|
354
|
+
|
|
355
|
+
if not opts.dry_run:
|
|
356
|
+
qs.generate(d, silent=True, overwrite=opts.force, templatedir=opts.template_dir)
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"""Sphinx extension for auto-generating API documentation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import fnmatch
|
|
6
|
+
import re
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from sphinx._cli.util.colour import bold
|
|
11
|
+
from sphinx.ext.apidoc._generate import create_modules_toc_file, recurse_tree
|
|
12
|
+
from sphinx.ext.apidoc._shared import (
|
|
13
|
+
LOGGER,
|
|
14
|
+
ApidocDefaults,
|
|
15
|
+
ApidocOptions,
|
|
16
|
+
_remove_old_files,
|
|
17
|
+
)
|
|
18
|
+
from sphinx.locale import __
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from collections.abc import Collection, Sequence
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
from sphinx.application import Sphinx
|
|
25
|
+
|
|
26
|
+
_BOOL_KEYS = frozenset({
|
|
27
|
+
'follow_links',
|
|
28
|
+
'separate_modules',
|
|
29
|
+
'include_private',
|
|
30
|
+
'no_headings',
|
|
31
|
+
'module_first',
|
|
32
|
+
'implicit_namespaces',
|
|
33
|
+
})
|
|
34
|
+
_ALLOWED_KEYS = _BOOL_KEYS | frozenset({
|
|
35
|
+
'path',
|
|
36
|
+
'destination',
|
|
37
|
+
'exclude_patterns',
|
|
38
|
+
'automodule_options',
|
|
39
|
+
'max_depth',
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def run_apidoc(app: Sphinx) -> None:
|
|
44
|
+
"""Run the apidoc extension."""
|
|
45
|
+
defaults = ApidocDefaults.from_config(app.config)
|
|
46
|
+
apidoc_modules: Sequence[dict[str, Any]] = app.config.apidoc_modules
|
|
47
|
+
srcdir: Path = app.srcdir
|
|
48
|
+
confdir: Path = app.confdir
|
|
49
|
+
|
|
50
|
+
LOGGER.info(bold(__('Running apidoc')))
|
|
51
|
+
|
|
52
|
+
module_options: dict[str, Any]
|
|
53
|
+
for i, module_options in enumerate(apidoc_modules):
|
|
54
|
+
_run_apidoc_module(
|
|
55
|
+
i,
|
|
56
|
+
options=module_options,
|
|
57
|
+
defaults=defaults,
|
|
58
|
+
srcdir=srcdir,
|
|
59
|
+
confdir=confdir,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _run_apidoc_module(
|
|
64
|
+
i: int,
|
|
65
|
+
*,
|
|
66
|
+
options: dict[str, Any],
|
|
67
|
+
defaults: ApidocDefaults,
|
|
68
|
+
srcdir: Path,
|
|
69
|
+
confdir: Path,
|
|
70
|
+
) -> None:
|
|
71
|
+
"""Run apidoc for a single module."""
|
|
72
|
+
args = _parse_module_options(
|
|
73
|
+
i, options=options, defaults=defaults, srcdir=srcdir, confdir=confdir
|
|
74
|
+
)
|
|
75
|
+
if args is None:
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
exclude_patterns_compiled: list[re.Pattern[str]] = [
|
|
79
|
+
re.compile(fnmatch.translate(exclude)) for exclude in args.exclude_pattern
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
written_files, modules = recurse_tree(
|
|
83
|
+
args.module_path, exclude_patterns_compiled, args, args.template_dir
|
|
84
|
+
)
|
|
85
|
+
if args.toc_file:
|
|
86
|
+
written_files.append(
|
|
87
|
+
create_modules_toc_file(modules, args, args.toc_file, args.template_dir)
|
|
88
|
+
)
|
|
89
|
+
if args.remove_old:
|
|
90
|
+
_remove_old_files(written_files, args.dest_dir, args.suffix)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _parse_module_options(
|
|
94
|
+
i: int,
|
|
95
|
+
*,
|
|
96
|
+
options: dict[str, Any],
|
|
97
|
+
defaults: ApidocDefaults,
|
|
98
|
+
srcdir: Path,
|
|
99
|
+
confdir: Path,
|
|
100
|
+
) -> ApidocOptions | None:
|
|
101
|
+
if not isinstance(options, dict):
|
|
102
|
+
LOGGER.warning(__('apidoc_modules item %i must be a dict'), i, type='apidoc')
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
# module path should be absolute or relative to the conf directory
|
|
106
|
+
try:
|
|
107
|
+
path = Path(options['path'])
|
|
108
|
+
except KeyError:
|
|
109
|
+
LOGGER.warning(
|
|
110
|
+
__("apidoc_modules item %i must have a 'path' key"), i, type='apidoc'
|
|
111
|
+
)
|
|
112
|
+
return None
|
|
113
|
+
except TypeError:
|
|
114
|
+
LOGGER.warning(
|
|
115
|
+
__("apidoc_modules item %i 'path' must be a string"), i, type='apidoc'
|
|
116
|
+
)
|
|
117
|
+
return None
|
|
118
|
+
module_path = confdir / path
|
|
119
|
+
if not module_path.is_dir():
|
|
120
|
+
LOGGER.warning(
|
|
121
|
+
__("apidoc_modules item %i 'path' is not an existing folder: %s"),
|
|
122
|
+
i,
|
|
123
|
+
module_path,
|
|
124
|
+
type='apidoc',
|
|
125
|
+
)
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
# destination path should be relative to the source directory
|
|
129
|
+
try:
|
|
130
|
+
destination = Path(options['destination'])
|
|
131
|
+
except KeyError:
|
|
132
|
+
LOGGER.warning(
|
|
133
|
+
__("apidoc_modules item %i must have a 'destination' key"),
|
|
134
|
+
i,
|
|
135
|
+
type='apidoc',
|
|
136
|
+
)
|
|
137
|
+
return None
|
|
138
|
+
except TypeError:
|
|
139
|
+
LOGGER.warning(
|
|
140
|
+
__("apidoc_modules item %i 'destination' must be a string"),
|
|
141
|
+
i,
|
|
142
|
+
type='apidoc',
|
|
143
|
+
)
|
|
144
|
+
return None
|
|
145
|
+
if destination.is_absolute():
|
|
146
|
+
LOGGER.warning(
|
|
147
|
+
__("apidoc_modules item %i 'destination' should be a relative path"),
|
|
148
|
+
i,
|
|
149
|
+
type='apidoc',
|
|
150
|
+
)
|
|
151
|
+
return None
|
|
152
|
+
dest_path = srcdir / destination
|
|
153
|
+
try:
|
|
154
|
+
dest_path.mkdir(parents=True, exist_ok=True)
|
|
155
|
+
except OSError as exc:
|
|
156
|
+
LOGGER.warning(
|
|
157
|
+
__('apidoc_modules item %i cannot create destination directory: %s'),
|
|
158
|
+
i,
|
|
159
|
+
exc.strerror,
|
|
160
|
+
type='apidoc',
|
|
161
|
+
)
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
# exclude patterns should be absolute or relative to the conf directory
|
|
165
|
+
exclude_patterns: list[str] = [
|
|
166
|
+
str(confdir / pattern)
|
|
167
|
+
for pattern in _check_collection_of_strings(
|
|
168
|
+
i, options, key='exclude_patterns', default=defaults.exclude_patterns
|
|
169
|
+
)
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
# TODO template_dir
|
|
173
|
+
|
|
174
|
+
max_depth = defaults.max_depth
|
|
175
|
+
if 'max_depth' in options:
|
|
176
|
+
if not isinstance(options['max_depth'], int):
|
|
177
|
+
LOGGER.warning(
|
|
178
|
+
__("apidoc_modules item %i '%s' must be an int"),
|
|
179
|
+
i,
|
|
180
|
+
'max_depth',
|
|
181
|
+
type='apidoc',
|
|
182
|
+
)
|
|
183
|
+
else:
|
|
184
|
+
max_depth = options['max_depth']
|
|
185
|
+
|
|
186
|
+
bool_options: dict[str, bool] = {}
|
|
187
|
+
for key in sorted(_BOOL_KEYS):
|
|
188
|
+
if key not in options:
|
|
189
|
+
bool_options[key] = getattr(defaults, key)
|
|
190
|
+
elif not isinstance(options[key], bool):
|
|
191
|
+
LOGGER.warning(
|
|
192
|
+
__("apidoc_modules item %i '%s' must be a boolean"),
|
|
193
|
+
i,
|
|
194
|
+
key,
|
|
195
|
+
type='apidoc',
|
|
196
|
+
)
|
|
197
|
+
bool_options[key] = getattr(defaults, key)
|
|
198
|
+
else:
|
|
199
|
+
bool_options[key] = options[key]
|
|
200
|
+
|
|
201
|
+
# TODO per-module automodule_options
|
|
202
|
+
automodule_options = frozenset(
|
|
203
|
+
_check_collection_of_strings(
|
|
204
|
+
i, options, key='automodule_options', default=defaults.automodule_options
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if diff := options.keys() - _ALLOWED_KEYS:
|
|
209
|
+
LOGGER.warning(
|
|
210
|
+
__('apidoc_modules item %i has unexpected keys: %s'),
|
|
211
|
+
i,
|
|
212
|
+
', '.join(sorted(diff)),
|
|
213
|
+
type='apidoc',
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
return ApidocOptions(
|
|
217
|
+
dest_dir=dest_path,
|
|
218
|
+
module_path=module_path,
|
|
219
|
+
exclude_pattern=exclude_patterns,
|
|
220
|
+
automodule_options=automodule_options,
|
|
221
|
+
max_depth=max_depth,
|
|
222
|
+
quiet=True,
|
|
223
|
+
follow_links=bool_options['follow_links'],
|
|
224
|
+
separate_modules=bool_options['separate_modules'],
|
|
225
|
+
include_private=bool_options['include_private'],
|
|
226
|
+
no_headings=bool_options['no_headings'],
|
|
227
|
+
module_first=bool_options['module_first'],
|
|
228
|
+
implicit_namespaces=bool_options['implicit_namespaces'],
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _check_collection_of_strings(
|
|
233
|
+
index: int,
|
|
234
|
+
options: dict[str, Any],
|
|
235
|
+
*,
|
|
236
|
+
key: str,
|
|
237
|
+
default: Collection[str],
|
|
238
|
+
) -> Collection[str]:
|
|
239
|
+
"""Check that a key's value is a collection of strings in the options.
|
|
240
|
+
|
|
241
|
+
:returns: The value of the key, or None if invalid.
|
|
242
|
+
"""
|
|
243
|
+
if key not in options:
|
|
244
|
+
return default
|
|
245
|
+
if not isinstance(options[key], list | tuple | set | frozenset):
|
|
246
|
+
LOGGER.warning(
|
|
247
|
+
__("apidoc_modules item %i '%s' must be a sequence"),
|
|
248
|
+
index,
|
|
249
|
+
key,
|
|
250
|
+
type='apidoc',
|
|
251
|
+
)
|
|
252
|
+
return default
|
|
253
|
+
for item in options[key]:
|
|
254
|
+
if not isinstance(item, str):
|
|
255
|
+
LOGGER.warning(
|
|
256
|
+
__("apidoc_modules item %i '%s' must contain strings"),
|
|
257
|
+
index,
|
|
258
|
+
key,
|
|
259
|
+
type='apidoc',
|
|
260
|
+
)
|
|
261
|
+
return default
|
|
262
|
+
return options[key]
|