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/apidoc.py
DELETED
|
@@ -1,721 +0,0 @@
|
|
|
1
|
-
"""Creates reST files corresponding to Python modules for code documentation.
|
|
2
|
-
|
|
3
|
-
Parses a directory tree looking for Python modules and packages and creates
|
|
4
|
-
ReST files appropriately to create code documentation with Sphinx. It also
|
|
5
|
-
creates a modules index (named modules.<suffix>).
|
|
6
|
-
|
|
7
|
-
This is derived from the "sphinx-autopackage" script, which is:
|
|
8
|
-
Copyright 2008 Société des arts technologiques (SAT),
|
|
9
|
-
https://sat.qc.ca/
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
from __future__ import annotations
|
|
13
|
-
|
|
14
|
-
import argparse
|
|
15
|
-
import fnmatch
|
|
16
|
-
import glob
|
|
17
|
-
import locale
|
|
18
|
-
import os
|
|
19
|
-
import re
|
|
20
|
-
import sys
|
|
21
|
-
from copy import copy
|
|
22
|
-
from importlib.machinery import EXTENSION_SUFFIXES
|
|
23
|
-
from os import path
|
|
24
|
-
from pathlib import Path
|
|
25
|
-
from typing import TYPE_CHECKING, Any, Protocol
|
|
26
|
-
|
|
27
|
-
import sphinx.locale
|
|
28
|
-
from sphinx import __display_version__, package_dir
|
|
29
|
-
from sphinx.cmd.quickstart import EXTENSIONS
|
|
30
|
-
from sphinx.locale import __
|
|
31
|
-
from sphinx.util import logging
|
|
32
|
-
from sphinx.util.osutil import FileAvoidWrite, ensuredir
|
|
33
|
-
from sphinx.util.template import ReSTRenderer
|
|
34
|
-
|
|
35
|
-
if TYPE_CHECKING:
|
|
36
|
-
from collections.abc import Iterator, Sequence
|
|
37
|
-
|
|
38
|
-
logger = logging.getLogger(__name__)
|
|
39
|
-
|
|
40
|
-
# automodule options
|
|
41
|
-
if 'SPHINX_APIDOC_OPTIONS' in os.environ:
|
|
42
|
-
OPTIONS = os.environ['SPHINX_APIDOC_OPTIONS'].split(',')
|
|
43
|
-
else:
|
|
44
|
-
OPTIONS = [
|
|
45
|
-
'members',
|
|
46
|
-
'undoc-members',
|
|
47
|
-
# 'inherited-members', # disabled because there's a bug in sphinx
|
|
48
|
-
'show-inheritance',
|
|
49
|
-
]
|
|
50
|
-
|
|
51
|
-
PY_SUFFIXES = ('.py', '.pyx', *tuple(EXTENSION_SUFFIXES))
|
|
52
|
-
|
|
53
|
-
template_dir = path.join(package_dir, 'templates', 'apidoc')
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def is_initpy(filename: str | Path) -> bool:
|
|
57
|
-
"""Check *filename* is __init__ file or not."""
|
|
58
|
-
basename = Path(filename).name
|
|
59
|
-
return any(
|
|
60
|
-
basename == '__init__' + suffix
|
|
61
|
-
for suffix in sorted(PY_SUFFIXES, key=len, reverse=True)
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def module_join(*modnames: str | None) -> str:
|
|
66
|
-
"""Join module names with dots."""
|
|
67
|
-
return '.'.join(filter(None, modnames))
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def is_packagedir(dirname: str | None = None, files: list[str] | None = None) -> bool:
|
|
71
|
-
"""Check given *files* contains __init__ file."""
|
|
72
|
-
if files is None and dirname is None:
|
|
73
|
-
return False
|
|
74
|
-
|
|
75
|
-
if files is None:
|
|
76
|
-
files = os.listdir(dirname)
|
|
77
|
-
return any(f for f in files if is_initpy(f))
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def write_file(name: str, text: str, opts: CliOptions) -> Path:
|
|
81
|
-
"""Write the output file for module/package <name>."""
|
|
82
|
-
fname = Path(opts.destdir, f'{name}.{opts.suffix}')
|
|
83
|
-
if opts.dryrun:
|
|
84
|
-
if not opts.quiet:
|
|
85
|
-
logger.info(__('Would create file %s.'), fname)
|
|
86
|
-
return fname
|
|
87
|
-
if not opts.force and fname.is_file():
|
|
88
|
-
if not opts.quiet:
|
|
89
|
-
logger.info(__('File %s already exists, skipping.'), fname)
|
|
90
|
-
else:
|
|
91
|
-
if not opts.quiet:
|
|
92
|
-
logger.info(__('Creating file %s.'), fname)
|
|
93
|
-
with FileAvoidWrite(fname) as f:
|
|
94
|
-
f.write(text)
|
|
95
|
-
return fname
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def create_module_file(
|
|
99
|
-
package: str | None,
|
|
100
|
-
basename: str,
|
|
101
|
-
opts: CliOptions,
|
|
102
|
-
user_template_dir: str | None = None,
|
|
103
|
-
) -> Path:
|
|
104
|
-
"""Build the text of the file and write the file."""
|
|
105
|
-
options = copy(OPTIONS)
|
|
106
|
-
if opts.includeprivate and 'private-members' not in options:
|
|
107
|
-
options.append('private-members')
|
|
108
|
-
|
|
109
|
-
qualname = module_join(package, basename)
|
|
110
|
-
context = {
|
|
111
|
-
'show_headings': not opts.noheadings,
|
|
112
|
-
'basename': basename,
|
|
113
|
-
'qualname': qualname,
|
|
114
|
-
'automodule_options': options,
|
|
115
|
-
}
|
|
116
|
-
if user_template_dir is not None:
|
|
117
|
-
template_path = [user_template_dir, template_dir]
|
|
118
|
-
else:
|
|
119
|
-
template_path = [template_dir]
|
|
120
|
-
text = ReSTRenderer(template_path).render('module.rst.jinja', context)
|
|
121
|
-
return write_file(qualname, text, opts)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def create_package_file(
|
|
125
|
-
root: str,
|
|
126
|
-
master_package: str | None,
|
|
127
|
-
subroot: str,
|
|
128
|
-
py_files: list[str],
|
|
129
|
-
opts: CliOptions,
|
|
130
|
-
subs: list[str],
|
|
131
|
-
is_namespace: bool,
|
|
132
|
-
excludes: Sequence[re.Pattern[str]] = (),
|
|
133
|
-
user_template_dir: str | None = None,
|
|
134
|
-
) -> list[Path]:
|
|
135
|
-
"""Build the text of the file and write the file.
|
|
136
|
-
|
|
137
|
-
Also create submodules if necessary.
|
|
138
|
-
|
|
139
|
-
:returns: list of written files
|
|
140
|
-
"""
|
|
141
|
-
# build a list of sub packages (directories containing an __init__ file)
|
|
142
|
-
subpackages = [
|
|
143
|
-
module_join(master_package, subroot, pkgname)
|
|
144
|
-
for pkgname in subs
|
|
145
|
-
if not is_skipped_package(Path(root, pkgname), opts, excludes)
|
|
146
|
-
]
|
|
147
|
-
# build a list of sub modules
|
|
148
|
-
submodules = [
|
|
149
|
-
sub.split('.')[0]
|
|
150
|
-
for sub in py_files
|
|
151
|
-
if not is_skipped_module(Path(root, sub), opts, excludes) and not is_initpy(sub)
|
|
152
|
-
]
|
|
153
|
-
submodules = sorted(set(submodules))
|
|
154
|
-
submodules = [
|
|
155
|
-
module_join(master_package, subroot, modname) for modname in submodules
|
|
156
|
-
]
|
|
157
|
-
options = copy(OPTIONS)
|
|
158
|
-
if opts.includeprivate and 'private-members' not in options:
|
|
159
|
-
options.append('private-members')
|
|
160
|
-
|
|
161
|
-
pkgname = module_join(master_package, subroot)
|
|
162
|
-
context = {
|
|
163
|
-
'pkgname': pkgname,
|
|
164
|
-
'subpackages': subpackages,
|
|
165
|
-
'submodules': submodules,
|
|
166
|
-
'is_namespace': is_namespace,
|
|
167
|
-
'modulefirst': opts.modulefirst,
|
|
168
|
-
'separatemodules': opts.separatemodules,
|
|
169
|
-
'automodule_options': options,
|
|
170
|
-
'show_headings': not opts.noheadings,
|
|
171
|
-
'maxdepth': opts.maxdepth,
|
|
172
|
-
}
|
|
173
|
-
if user_template_dir is not None:
|
|
174
|
-
template_path = [user_template_dir, template_dir]
|
|
175
|
-
else:
|
|
176
|
-
template_path = [template_dir]
|
|
177
|
-
|
|
178
|
-
written: list[Path] = []
|
|
179
|
-
|
|
180
|
-
text = ReSTRenderer(template_path).render('package.rst.jinja', context)
|
|
181
|
-
written.append(write_file(pkgname, text, opts))
|
|
182
|
-
|
|
183
|
-
if submodules and opts.separatemodules:
|
|
184
|
-
written.extend([
|
|
185
|
-
create_module_file(None, submodule, opts, user_template_dir)
|
|
186
|
-
for submodule in submodules
|
|
187
|
-
])
|
|
188
|
-
|
|
189
|
-
return written
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def create_modules_toc_file(
|
|
193
|
-
modules: list[str],
|
|
194
|
-
opts: CliOptions,
|
|
195
|
-
name: str = 'modules',
|
|
196
|
-
user_template_dir: str | None = None,
|
|
197
|
-
) -> Path:
|
|
198
|
-
"""Create the module's index."""
|
|
199
|
-
modules.sort()
|
|
200
|
-
prev_module = ''
|
|
201
|
-
for module in modules.copy():
|
|
202
|
-
# look if the module is a subpackage and, if yes, ignore it
|
|
203
|
-
if module.startswith(prev_module + '.'):
|
|
204
|
-
modules.remove(module)
|
|
205
|
-
else:
|
|
206
|
-
prev_module = module
|
|
207
|
-
|
|
208
|
-
context = {
|
|
209
|
-
'header': opts.header,
|
|
210
|
-
'maxdepth': opts.maxdepth,
|
|
211
|
-
'docnames': modules,
|
|
212
|
-
}
|
|
213
|
-
if user_template_dir is not None:
|
|
214
|
-
template_path = [user_template_dir, template_dir]
|
|
215
|
-
else:
|
|
216
|
-
template_path = [template_dir]
|
|
217
|
-
text = ReSTRenderer(template_path).render('toc.rst.jinja', context)
|
|
218
|
-
return write_file(name, text, opts)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def is_skipped_package(
|
|
222
|
-
dirname: str | Path, opts: CliOptions, excludes: Sequence[re.Pattern[str]] = ()
|
|
223
|
-
) -> bool:
|
|
224
|
-
"""Check if we want to skip this module."""
|
|
225
|
-
if not Path(dirname).is_dir():
|
|
226
|
-
return False
|
|
227
|
-
|
|
228
|
-
files = glob.glob(str(Path(dirname, '*.py')))
|
|
229
|
-
regular_package = any(f for f in files if is_initpy(f))
|
|
230
|
-
if not regular_package and not opts.implicit_namespaces:
|
|
231
|
-
# *dirname* is not both a regular package and an implicit namespace package
|
|
232
|
-
return True
|
|
233
|
-
|
|
234
|
-
# Check there is some showable module inside package
|
|
235
|
-
return all(is_excluded(Path(dirname, f), excludes) for f in files)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def is_skipped_module(
|
|
239
|
-
filename: str | Path, opts: CliOptions, _excludes: Sequence[re.Pattern[str]]
|
|
240
|
-
) -> bool:
|
|
241
|
-
"""Check if we want to skip this module."""
|
|
242
|
-
filename = Path(filename)
|
|
243
|
-
if not filename.exists():
|
|
244
|
-
# skip if the file doesn't exist
|
|
245
|
-
return True
|
|
246
|
-
# skip if the module has a "private" name
|
|
247
|
-
return filename.name.startswith('_') and not opts.includeprivate
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def walk(
|
|
251
|
-
rootpath: str,
|
|
252
|
-
excludes: Sequence[re.Pattern[str]],
|
|
253
|
-
opts: CliOptions,
|
|
254
|
-
) -> Iterator[tuple[str, list[str], list[str]]]:
|
|
255
|
-
"""Walk through the directory and list files and subdirectories up."""
|
|
256
|
-
for root, subs, files in os.walk(rootpath, followlinks=opts.followlinks):
|
|
257
|
-
# document only Python module files (that aren't excluded)
|
|
258
|
-
files = sorted(
|
|
259
|
-
f
|
|
260
|
-
for f in files
|
|
261
|
-
if f.endswith(PY_SUFFIXES) and not is_excluded(Path(root, f), excludes)
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
# remove hidden ('.') and private ('_') directories, as well as
|
|
265
|
-
# excluded dirs
|
|
266
|
-
if opts.includeprivate:
|
|
267
|
-
exclude_prefixes: tuple[str, ...] = ('.',)
|
|
268
|
-
else:
|
|
269
|
-
exclude_prefixes = ('.', '_')
|
|
270
|
-
|
|
271
|
-
subs[:] = sorted(
|
|
272
|
-
sub
|
|
273
|
-
for sub in subs
|
|
274
|
-
if not sub.startswith(exclude_prefixes)
|
|
275
|
-
and not is_excluded(Path(root, sub), excludes)
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
yield root, subs, files
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
def has_child_module(
|
|
282
|
-
rootpath: str, excludes: Sequence[re.Pattern[str]], opts: CliOptions
|
|
283
|
-
) -> bool:
|
|
284
|
-
"""Check the given directory contains child module/s (at least one)."""
|
|
285
|
-
return any(files for _root, _subs, files in walk(rootpath, excludes, opts))
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
def recurse_tree(
|
|
289
|
-
rootpath: str,
|
|
290
|
-
excludes: Sequence[re.Pattern[str]],
|
|
291
|
-
opts: CliOptions,
|
|
292
|
-
user_template_dir: str | None = None,
|
|
293
|
-
) -> tuple[list[Path], list[str]]:
|
|
294
|
-
"""
|
|
295
|
-
Look for every file in the directory tree and create the corresponding
|
|
296
|
-
ReST files.
|
|
297
|
-
"""
|
|
298
|
-
# check if the base directory is a package and get its name
|
|
299
|
-
if is_packagedir(rootpath) or opts.implicit_namespaces:
|
|
300
|
-
root_package = rootpath.split(path.sep)[-1]
|
|
301
|
-
else:
|
|
302
|
-
# otherwise, the base is a directory with packages
|
|
303
|
-
root_package = None
|
|
304
|
-
|
|
305
|
-
toplevels = []
|
|
306
|
-
written_files = []
|
|
307
|
-
for root, subs, files in walk(rootpath, excludes, opts):
|
|
308
|
-
is_pkg = is_packagedir(None, files)
|
|
309
|
-
is_namespace = not is_pkg and opts.implicit_namespaces
|
|
310
|
-
if is_pkg:
|
|
311
|
-
for f in files.copy():
|
|
312
|
-
if is_initpy(f):
|
|
313
|
-
files.remove(f)
|
|
314
|
-
files.insert(0, f)
|
|
315
|
-
elif root != rootpath:
|
|
316
|
-
# only accept non-package at toplevel unless using implicit namespaces
|
|
317
|
-
if not opts.implicit_namespaces:
|
|
318
|
-
subs.clear()
|
|
319
|
-
continue
|
|
320
|
-
|
|
321
|
-
if is_pkg or is_namespace:
|
|
322
|
-
# we are in a package with something to document
|
|
323
|
-
if subs or len(files) > 1 or not is_skipped_package(root, opts):
|
|
324
|
-
subpackage = (
|
|
325
|
-
root[len(rootpath) :].lstrip(path.sep).replace(path.sep, '.')
|
|
326
|
-
)
|
|
327
|
-
# if this is not a namespace or
|
|
328
|
-
# a namespace and there is something there to document
|
|
329
|
-
if not is_namespace or has_child_module(root, excludes, opts):
|
|
330
|
-
written_files.extend(
|
|
331
|
-
create_package_file(
|
|
332
|
-
root,
|
|
333
|
-
root_package,
|
|
334
|
-
subpackage,
|
|
335
|
-
files,
|
|
336
|
-
opts,
|
|
337
|
-
subs,
|
|
338
|
-
is_namespace,
|
|
339
|
-
excludes,
|
|
340
|
-
user_template_dir,
|
|
341
|
-
)
|
|
342
|
-
)
|
|
343
|
-
toplevels.append(module_join(root_package, subpackage))
|
|
344
|
-
else:
|
|
345
|
-
# if we are at the root level, we don't require it to be a package
|
|
346
|
-
assert root == rootpath
|
|
347
|
-
assert root_package is None
|
|
348
|
-
for py_file in files:
|
|
349
|
-
if not is_skipped_module(Path(rootpath, py_file), opts, excludes):
|
|
350
|
-
module = py_file.split('.')[0]
|
|
351
|
-
written_files.append(
|
|
352
|
-
create_module_file(
|
|
353
|
-
root_package, module, opts, user_template_dir
|
|
354
|
-
)
|
|
355
|
-
)
|
|
356
|
-
toplevels.append(module)
|
|
357
|
-
|
|
358
|
-
return written_files, toplevels
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
def is_excluded(root: str | Path, excludes: Sequence[re.Pattern[str]]) -> bool:
|
|
362
|
-
"""Check if the directory is in the exclude list.
|
|
363
|
-
|
|
364
|
-
Note: by having trailing slashes, we avoid common prefix issues, like
|
|
365
|
-
e.g. an exclude "foo" also accidentally excluding "foobar".
|
|
366
|
-
"""
|
|
367
|
-
root_str = str(root)
|
|
368
|
-
return any(exclude.match(root_str) for exclude in excludes)
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
def get_parser() -> argparse.ArgumentParser:
|
|
372
|
-
parser = argparse.ArgumentParser(
|
|
373
|
-
usage='%(prog)s [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH> [EXCLUDE_PATTERN, ...]',
|
|
374
|
-
epilog=__('For more information, visit <https://www.sphinx-doc.org/>.'),
|
|
375
|
-
description=__("""
|
|
376
|
-
Look recursively in <MODULE_PATH> for Python modules and packages and create
|
|
377
|
-
one reST file with automodule directives per package in the <OUTPUT_PATH>.
|
|
378
|
-
|
|
379
|
-
The <EXCLUDE_PATTERN>s can be file and/or directory patterns that will be
|
|
380
|
-
excluded from generation.
|
|
381
|
-
|
|
382
|
-
Note: By default this script will not overwrite already created files."""),
|
|
383
|
-
)
|
|
384
|
-
|
|
385
|
-
parser.add_argument(
|
|
386
|
-
'--version',
|
|
387
|
-
action='version',
|
|
388
|
-
dest='show_version',
|
|
389
|
-
version='%%(prog)s %s' % __display_version__,
|
|
390
|
-
)
|
|
391
|
-
|
|
392
|
-
parser.add_argument('module_path', help=__('path to module to document'))
|
|
393
|
-
parser.add_argument(
|
|
394
|
-
'exclude_pattern',
|
|
395
|
-
nargs='*',
|
|
396
|
-
help=__(
|
|
397
|
-
'fnmatch-style file and/or directory patterns to exclude from generation'
|
|
398
|
-
),
|
|
399
|
-
)
|
|
400
|
-
|
|
401
|
-
parser.add_argument(
|
|
402
|
-
'-o',
|
|
403
|
-
'--output-dir',
|
|
404
|
-
action='store',
|
|
405
|
-
dest='destdir',
|
|
406
|
-
required=True,
|
|
407
|
-
help=__('directory to place all output'),
|
|
408
|
-
)
|
|
409
|
-
parser.add_argument(
|
|
410
|
-
'-q',
|
|
411
|
-
action='store_true',
|
|
412
|
-
dest='quiet',
|
|
413
|
-
help=__('no output on stdout, just warnings on stderr'),
|
|
414
|
-
)
|
|
415
|
-
parser.add_argument(
|
|
416
|
-
'-d',
|
|
417
|
-
'--maxdepth',
|
|
418
|
-
action='store',
|
|
419
|
-
dest='maxdepth',
|
|
420
|
-
type=int,
|
|
421
|
-
default=4,
|
|
422
|
-
help=__('maximum depth of submodules to show in the TOC (default: 4)'),
|
|
423
|
-
)
|
|
424
|
-
parser.add_argument(
|
|
425
|
-
'-f',
|
|
426
|
-
'--force',
|
|
427
|
-
action='store_true',
|
|
428
|
-
dest='force',
|
|
429
|
-
help=__('overwrite existing files'),
|
|
430
|
-
)
|
|
431
|
-
parser.add_argument(
|
|
432
|
-
'-l',
|
|
433
|
-
'--follow-links',
|
|
434
|
-
action='store_true',
|
|
435
|
-
dest='followlinks',
|
|
436
|
-
default=False,
|
|
437
|
-
help=__(
|
|
438
|
-
'follow symbolic links. Powerful when combined with collective.recipe.omelette.'
|
|
439
|
-
),
|
|
440
|
-
)
|
|
441
|
-
parser.add_argument(
|
|
442
|
-
'-n',
|
|
443
|
-
'--dry-run',
|
|
444
|
-
action='store_true',
|
|
445
|
-
dest='dryrun',
|
|
446
|
-
help=__('run the script without creating files'),
|
|
447
|
-
)
|
|
448
|
-
parser.add_argument(
|
|
449
|
-
'-e',
|
|
450
|
-
'--separate',
|
|
451
|
-
action='store_true',
|
|
452
|
-
dest='separatemodules',
|
|
453
|
-
help=__('put documentation for each module on its own page'),
|
|
454
|
-
)
|
|
455
|
-
parser.add_argument(
|
|
456
|
-
'-P',
|
|
457
|
-
'--private',
|
|
458
|
-
action='store_true',
|
|
459
|
-
dest='includeprivate',
|
|
460
|
-
help=__('include "_private" modules'),
|
|
461
|
-
)
|
|
462
|
-
parser.add_argument(
|
|
463
|
-
'--tocfile',
|
|
464
|
-
action='store',
|
|
465
|
-
dest='tocfile',
|
|
466
|
-
default='modules',
|
|
467
|
-
help=__('filename of table of contents (default: modules)'),
|
|
468
|
-
)
|
|
469
|
-
parser.add_argument(
|
|
470
|
-
'-T',
|
|
471
|
-
'--no-toc',
|
|
472
|
-
action='store_false',
|
|
473
|
-
dest='tocfile',
|
|
474
|
-
help=__("don't create a table of contents file"),
|
|
475
|
-
)
|
|
476
|
-
parser.add_argument(
|
|
477
|
-
'-E',
|
|
478
|
-
'--no-headings',
|
|
479
|
-
action='store_true',
|
|
480
|
-
dest='noheadings',
|
|
481
|
-
help=__(
|
|
482
|
-
"don't create headings for the module/package "
|
|
483
|
-
'packages (e.g. when the docstrings already '
|
|
484
|
-
'contain them)'
|
|
485
|
-
),
|
|
486
|
-
)
|
|
487
|
-
parser.add_argument(
|
|
488
|
-
'-M',
|
|
489
|
-
'--module-first',
|
|
490
|
-
action='store_true',
|
|
491
|
-
dest='modulefirst',
|
|
492
|
-
help=__('put module documentation before submodule documentation'),
|
|
493
|
-
)
|
|
494
|
-
parser.add_argument(
|
|
495
|
-
'--implicit-namespaces',
|
|
496
|
-
action='store_true',
|
|
497
|
-
dest='implicit_namespaces',
|
|
498
|
-
help=__(
|
|
499
|
-
'interpret module paths according to PEP-0420 implicit namespaces specification'
|
|
500
|
-
),
|
|
501
|
-
)
|
|
502
|
-
parser.add_argument(
|
|
503
|
-
'-s',
|
|
504
|
-
'--suffix',
|
|
505
|
-
action='store',
|
|
506
|
-
dest='suffix',
|
|
507
|
-
default='rst',
|
|
508
|
-
help=__('file suffix (default: rst)'),
|
|
509
|
-
)
|
|
510
|
-
exclusive_group = parser.add_mutually_exclusive_group()
|
|
511
|
-
exclusive_group.add_argument(
|
|
512
|
-
'--remove-old',
|
|
513
|
-
action='store_true',
|
|
514
|
-
dest='remove_old',
|
|
515
|
-
help=__(
|
|
516
|
-
'Remove existing files in the output directory that were not generated'
|
|
517
|
-
),
|
|
518
|
-
)
|
|
519
|
-
exclusive_group.add_argument(
|
|
520
|
-
'-F',
|
|
521
|
-
'--full',
|
|
522
|
-
action='store_true',
|
|
523
|
-
dest='full',
|
|
524
|
-
help=__('generate a full project with sphinx-quickstart'),
|
|
525
|
-
)
|
|
526
|
-
parser.add_argument(
|
|
527
|
-
'-a',
|
|
528
|
-
'--append-syspath',
|
|
529
|
-
action='store_true',
|
|
530
|
-
dest='append_syspath',
|
|
531
|
-
help=__('append module_path to sys.path, used when --full is given'),
|
|
532
|
-
)
|
|
533
|
-
parser.add_argument(
|
|
534
|
-
'-H',
|
|
535
|
-
'--doc-project',
|
|
536
|
-
action='store',
|
|
537
|
-
dest='header',
|
|
538
|
-
help=__('project name (default: root module name)'),
|
|
539
|
-
)
|
|
540
|
-
parser.add_argument(
|
|
541
|
-
'-A',
|
|
542
|
-
'--doc-author',
|
|
543
|
-
action='store',
|
|
544
|
-
dest='author',
|
|
545
|
-
help=__('project author(s), used when --full is given'),
|
|
546
|
-
)
|
|
547
|
-
parser.add_argument(
|
|
548
|
-
'-V',
|
|
549
|
-
'--doc-version',
|
|
550
|
-
action='store',
|
|
551
|
-
dest='version',
|
|
552
|
-
help=__('project version, used when --full is given'),
|
|
553
|
-
)
|
|
554
|
-
parser.add_argument(
|
|
555
|
-
'-R',
|
|
556
|
-
'--doc-release',
|
|
557
|
-
action='store',
|
|
558
|
-
dest='release',
|
|
559
|
-
help=__(
|
|
560
|
-
'project release, used when --full is given, defaults to --doc-version'
|
|
561
|
-
),
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
group = parser.add_argument_group(__('extension options'))
|
|
565
|
-
group.add_argument(
|
|
566
|
-
'--extensions',
|
|
567
|
-
metavar='EXTENSIONS',
|
|
568
|
-
dest='extensions',
|
|
569
|
-
action='append',
|
|
570
|
-
help=__('enable arbitrary extensions'),
|
|
571
|
-
)
|
|
572
|
-
for ext in EXTENSIONS:
|
|
573
|
-
group.add_argument(
|
|
574
|
-
'--ext-%s' % ext,
|
|
575
|
-
action='append_const',
|
|
576
|
-
const='sphinx.ext.%s' % ext,
|
|
577
|
-
dest='extensions',
|
|
578
|
-
help=__('enable %s extension') % ext,
|
|
579
|
-
)
|
|
580
|
-
|
|
581
|
-
group = parser.add_argument_group(__('Project templating'))
|
|
582
|
-
group.add_argument(
|
|
583
|
-
'-t',
|
|
584
|
-
'--templatedir',
|
|
585
|
-
metavar='TEMPLATEDIR',
|
|
586
|
-
dest='templatedir',
|
|
587
|
-
help=__('template directory for template files'),
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
return parser
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
class CliOptions(Protocol):
|
|
594
|
-
"""Arguments parsed from the command line."""
|
|
595
|
-
|
|
596
|
-
module_path: str
|
|
597
|
-
exclude_pattern: list[str]
|
|
598
|
-
destdir: str
|
|
599
|
-
quiet: bool
|
|
600
|
-
maxdepth: int
|
|
601
|
-
force: bool
|
|
602
|
-
followlinks: bool
|
|
603
|
-
dryrun: bool
|
|
604
|
-
separatemodules: bool
|
|
605
|
-
includeprivate: bool
|
|
606
|
-
tocfile: str
|
|
607
|
-
noheadings: bool
|
|
608
|
-
modulefirst: bool
|
|
609
|
-
implicit_namespaces: bool
|
|
610
|
-
suffix: str
|
|
611
|
-
full: bool
|
|
612
|
-
append_syspath: bool
|
|
613
|
-
header: str | None
|
|
614
|
-
author: str | None
|
|
615
|
-
version: str | None
|
|
616
|
-
release: str | None
|
|
617
|
-
extensions: list[str] | None
|
|
618
|
-
templatedir: str | None
|
|
619
|
-
remove_old: bool
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
def main(argv: Sequence[str] = (), /) -> int:
|
|
623
|
-
"""Parse and check the command line arguments."""
|
|
624
|
-
locale.setlocale(locale.LC_ALL, '')
|
|
625
|
-
sphinx.locale.init_console()
|
|
626
|
-
|
|
627
|
-
parser = get_parser()
|
|
628
|
-
args: CliOptions = parser.parse_args(argv or sys.argv[1:])
|
|
629
|
-
|
|
630
|
-
rootpath = path.abspath(args.module_path)
|
|
631
|
-
|
|
632
|
-
# normalize opts
|
|
633
|
-
|
|
634
|
-
if args.header is None:
|
|
635
|
-
args.header = rootpath.split(path.sep)[-1]
|
|
636
|
-
args.suffix = args.suffix.removeprefix('.')
|
|
637
|
-
if not Path(rootpath).is_dir():
|
|
638
|
-
logger.error(__('%s is not a directory.'), rootpath)
|
|
639
|
-
raise SystemExit(1)
|
|
640
|
-
if not args.dryrun:
|
|
641
|
-
ensuredir(args.destdir)
|
|
642
|
-
excludes = tuple(
|
|
643
|
-
re.compile(fnmatch.translate(path.abspath(exclude)))
|
|
644
|
-
for exclude in dict.fromkeys(args.exclude_pattern)
|
|
645
|
-
)
|
|
646
|
-
written_files, modules = recurse_tree(rootpath, excludes, args, args.templatedir)
|
|
647
|
-
|
|
648
|
-
if args.full:
|
|
649
|
-
from sphinx.cmd import quickstart as qs
|
|
650
|
-
|
|
651
|
-
modules.sort()
|
|
652
|
-
prev_module = ''
|
|
653
|
-
text = ''
|
|
654
|
-
for module in modules:
|
|
655
|
-
if module.startswith(prev_module + '.'):
|
|
656
|
-
continue
|
|
657
|
-
prev_module = module
|
|
658
|
-
text += ' %s\n' % module
|
|
659
|
-
d: dict[str, Any] = {
|
|
660
|
-
'path': args.destdir,
|
|
661
|
-
'sep': False,
|
|
662
|
-
'dot': '_',
|
|
663
|
-
'project': args.header,
|
|
664
|
-
'author': args.author or 'Author',
|
|
665
|
-
'version': args.version or '',
|
|
666
|
-
'release': args.release or args.version or '',
|
|
667
|
-
'suffix': '.' + args.suffix,
|
|
668
|
-
'master': 'index',
|
|
669
|
-
'epub': True,
|
|
670
|
-
'extensions': [
|
|
671
|
-
'sphinx.ext.autodoc',
|
|
672
|
-
'sphinx.ext.viewcode',
|
|
673
|
-
'sphinx.ext.todo',
|
|
674
|
-
],
|
|
675
|
-
'makefile': True,
|
|
676
|
-
'batchfile': True,
|
|
677
|
-
'make_mode': True,
|
|
678
|
-
'mastertocmaxdepth': args.maxdepth,
|
|
679
|
-
'mastertoctree': text,
|
|
680
|
-
'language': 'en',
|
|
681
|
-
'module_path': rootpath,
|
|
682
|
-
'append_syspath': args.append_syspath,
|
|
683
|
-
}
|
|
684
|
-
if args.extensions:
|
|
685
|
-
d['extensions'].extend(args.extensions)
|
|
686
|
-
if args.quiet:
|
|
687
|
-
d['quiet'] = True
|
|
688
|
-
|
|
689
|
-
for ext in d['extensions'][:]:
|
|
690
|
-
if ',' in ext:
|
|
691
|
-
d['extensions'].remove(ext)
|
|
692
|
-
d['extensions'].extend(ext.split(','))
|
|
693
|
-
|
|
694
|
-
if not args.dryrun:
|
|
695
|
-
qs.generate(
|
|
696
|
-
d, silent=True, overwrite=args.force, templatedir=args.templatedir
|
|
697
|
-
)
|
|
698
|
-
elif args.tocfile:
|
|
699
|
-
written_files.append(
|
|
700
|
-
create_modules_toc_file(modules, args, args.tocfile, args.templatedir)
|
|
701
|
-
)
|
|
702
|
-
|
|
703
|
-
if args.remove_old and not args.dryrun:
|
|
704
|
-
for existing in Path(args.destdir).glob(f'**/*.{args.suffix}'):
|
|
705
|
-
if existing not in written_files:
|
|
706
|
-
try:
|
|
707
|
-
existing.unlink()
|
|
708
|
-
except OSError as exc:
|
|
709
|
-
logger.warning(
|
|
710
|
-
__('Failed to remove %s: %s'),
|
|
711
|
-
existing,
|
|
712
|
-
exc.strerror,
|
|
713
|
-
type='autodoc',
|
|
714
|
-
)
|
|
715
|
-
|
|
716
|
-
return 0
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
# So program can be started with "python -m sphinx.apidoc ..."
|
|
720
|
-
if __name__ == '__main__':
|
|
721
|
-
raise SystemExit(main(sys.argv[1:]))
|