|
1 | | -import subprocess |
2 | 1 | import sys |
3 | 2 | from datetime import date, datetime |
4 | 3 | from pathlib import Path |
| 4 | +from subprocess import check_output |
| 5 | +from typing import Any, Optional, Tuple, Union |
5 | 6 |
|
6 | 7 | import sphinx_rtd_theme |
| 8 | +from docutils.nodes import Element |
| 9 | +from sphinx.addnodes import pending_xref |
| 10 | +from sphinx.application import Sphinx |
| 11 | +from sphinx.builders import Builder |
| 12 | +from sphinx.environment import BuildEnvironment |
| 13 | +from sphinx.ext.autodoc import Options |
7 | 14 |
|
8 | 15 | from tox.version import __version__ |
9 | 16 |
|
|
17 | 24 | "sphinx.ext.autodoc", |
18 | 25 | "sphinx.ext.autosectionlabel", |
19 | 26 | "sphinx.ext.extlinks", |
| 27 | + "sphinx.ext.intersphinx", |
20 | 28 | "sphinx_argparse_cli", |
| 29 | + "sphinx_autodoc_typehints", |
| 30 | + "sphinx_inline_tabs", |
| 31 | + "sphinx_copybutton", |
21 | 32 | ] |
22 | 33 |
|
23 | 34 | templates_path = [] |
|
27 | 38 |
|
28 | 39 | master_doc = "index" |
29 | 40 | pygments_style = "default" |
30 | | -always_document_param_types = True |
| 41 | + |
31 | 42 | project = name |
32 | 43 | today_fmt = "%B %d, %Y" |
33 | 44 |
|
|
48 | 59 | html_logo = "_static/img/tox.svg" |
49 | 60 | html_favicon = "_static/img/toxfavi.ico" |
50 | 61 | htmlhelp_basename = "Pastedoc" |
51 | | -autoclass_content = "both" # Include __init__ in class documentation |
| 62 | + |
| 63 | +autoclass_content = "class" |
52 | 64 | autodoc_member_order = "bysource" |
| 65 | +autodoc_default_options = { |
| 66 | + "member-order": "bysource", |
| 67 | + "undoc-members": True, |
| 68 | + "show-inheritance": True, |
| 69 | +} |
| 70 | +autodoc_typehints = "none" |
| 71 | +always_document_param_types = False |
| 72 | +typehints_fully_qualified = True |
53 | 73 | autosectionlabel_prefix_document = True |
54 | 74 |
|
55 | 75 | extlinks = { |
|
58 | 78 | "user": ("https://github.com/%s", "@"), |
59 | 79 | "pypi": ("https://pypi.org/project/%s", ""), |
60 | 80 | } |
| 81 | +intersphinx_mapping = { |
| 82 | + "python": ("https://docs.python.org/3", None), |
| 83 | + "packaging": ("https://packaging.pypa.io/en/latest", None), |
| 84 | +} |
| 85 | +nitpicky = True |
| 86 | +nitpick_ignore = [] |
| 87 | + |
61 | 88 |
|
| 89 | +def skip_member(app: Sphinx, what: str, name: str, obj: Any, would_skip: bool, options: Options) -> bool: # noqa: U100 |
| 90 | + return True if name in options.get("exclude-members", set()) else would_skip |
62 | 91 |
|
63 | | -def generate_draft_news(): |
| 92 | + |
| 93 | +def process_signature( |
| 94 | + app: Sphinx, objtype: str, name: str, obj: Any, options: Options, args: str, retann: Optional[str] # noqa: U100 |
| 95 | +) -> Union[None, Tuple[None, None]]: |
| 96 | + # skip-member is not checked for class level docs, so disable via signature processing |
| 97 | + return (None, None) if objtype == "class" and "__init__" in options.get("exclude-members", set()) else None |
| 98 | + |
| 99 | + |
| 100 | +def setup(app: Sphinx) -> None: |
64 | 101 | root = Path(__file__).parents[1] |
65 | 102 | exe = Path(sys.executable) |
66 | 103 | towncrier = exe.with_name(f"towncrier{exe.suffix}") |
67 | | - new = subprocess.check_output([str(towncrier), "--draft", "--version", "NEXT"], cwd=root, universal_newlines=True) |
| 104 | + new = check_output([str(towncrier), "--draft", "--version", "NEXT"], cwd=root, universal_newlines=True) |
68 | 105 | (root / "docs" / "_draft.rst").write_text("" if "No significant changes" in new else new) |
69 | 106 |
|
| 107 | + from sphinx.domains.python import PythonDomain |
70 | 108 |
|
71 | | -generate_draft_news() |
| 109 | + class PatchedPythonDomain(PythonDomain): |
| 110 | + def resolve_xref( |
| 111 | + self, |
| 112 | + env: BuildEnvironment, |
| 113 | + fromdocname: str, |
| 114 | + builder: Builder, |
| 115 | + type: str, |
| 116 | + target: str, |
| 117 | + node: pending_xref, |
| 118 | + contnode: Element, |
| 119 | + ) -> Element: |
| 120 | + # fixup some wrongly resolved mappings |
| 121 | + mapping = { |
| 122 | + "_io.TextIOWrapper": "io.TextIOWrapper", |
| 123 | + "Future": "concurrent.futures.Future", |
| 124 | + "_F": "typing.TypeVar", |
| 125 | + "V": "typing.TypeVar", |
| 126 | + "T": "typing.TypeVar", |
| 127 | + "tox.config.of_type.T": "typing.TypeVar", |
| 128 | + "tox.config.loader.api.T": "typing.TypeVar", |
| 129 | + "tox.config.loader.convert.T": "typing.TypeVar", |
| 130 | + } |
| 131 | + if target in mapping: |
| 132 | + node["reftarget"] = mapping[target] |
| 133 | + return super().resolve_xref(env, fromdocname, builder, type, target, node, contnode) |
72 | 134 |
|
73 | | - |
74 | | -def setup(app): |
| 135 | + app.connect("autodoc-skip-member", skip_member) |
| 136 | + app.connect("autodoc-process-signature", process_signature, priority=400) |
| 137 | + app.add_domain(PatchedPythonDomain, override=True) |
75 | 138 | app.add_css_file("custom.css") |
76 | | - |
77 | | - # the CLI arguments are dynamically generated - do not cache |
78 | | - doc_tree = Path(app.doctreedir) |
79 | | - cli_interface_doctree = doc_tree / "cli_interface.doctree" |
80 | | - if cli_interface_doctree.exists(): |
81 | | - cli_interface_doctree.unlink() |
|
0 commit comments