3
3
import re
4
4
import sys
5
5
from datetime import date , datetime
6
+ from importlib .machinery import SourceFileLoader
6
7
from pathlib import Path
7
8
from subprocess import check_output
8
- from typing import Any , cast
9
+ from typing import Any
9
10
10
- from docutils .nodes import Element , Node , Text , container , fully_normalize_name , literal , paragraph , reference , strong
11
- from docutils .parsers .rst .directives import flag , unchanged , unchanged_required
12
- from docutils .parsers .rst .states import RSTState , RSTStateMachine
13
- from docutils .statemachine import StringList , string2lines
11
+ from docutils .nodes import Element , reference
14
12
from sphinx .addnodes import pending_xref
15
13
from sphinx .application import Sphinx
16
14
from sphinx .builders import Builder
17
- from sphinx .domains .std import StandardDomain
15
+ from sphinx .domains .python import PythonDomain
18
16
from sphinx .environment import BuildEnvironment
19
17
from sphinx .ext .autodoc import Options
20
18
from sphinx .ext .extlinks import ExternalLinksChecker
21
- from sphinx .locale import __
22
- from sphinx .util .docutils import SphinxDirective
23
- from sphinx .util .logging import getLogger
24
19
25
20
from tox import __version__
26
21
27
- company = "tox-dev"
28
- name = "tox"
29
- version = "." .join (__version__ .split ("." )[:2 ])
30
- release = __version__
22
+ company , name = "tox-dev" , "tox"
23
+ release , version = __version__ , "." .join (__version__ .split ("." )[:2 ])
31
24
copyright = f"2010-{ date .today ().year } , { company } "
25
+ master_doc , source_suffix = "index" , ".rst"
26
+
27
+ html_theme = "furo"
28
+ html_title , html_last_updated_fmt = "tox" , datetime .now ().isoformat ()
29
+ pygments_style , pygments_dark_style = "sphinx" , "monokai"
30
+ html_static_path , html_css_files = ["_static" ], ["custom.css" ]
31
+ html_logo , html_favicon = "_static/img/tox.svg" , "_static/img/toxfavi.ico"
32
32
33
33
extensions = [
34
34
"sphinx.ext.autodoc" ,
41
41
"sphinx_copybutton" ,
42
42
]
43
43
44
- templates_path = []
45
- unused_docs = []
46
- source_suffix = ".rst"
47
44
exclude_patterns = ["_build" , "changelog/*" , "_draft.rst" ]
48
-
49
- master_doc = "index"
50
- pygments_style = "default"
51
-
52
- project = name
53
- today_fmt = "%B %d, %Y"
54
-
55
- html_theme = "furo"
56
- html_theme_options = {
57
- "navigation_with_keys" : True ,
58
- }
59
- html_title = "tox 4 - rewrite"
60
- html_static_path = ["_static" ]
61
- html_css_files = ["custom.css" ]
62
- html_last_updated_fmt = datetime .now ().isoformat ()
63
- html_logo = "_static/img/tox.svg"
64
- html_favicon = "_static/img/toxfavi.ico"
65
-
66
- autoclass_content = "class"
67
- autodoc_member_order = "bysource"
45
+ autoclass_content , autodoc_member_order , autodoc_typehints = "class" , "bysource" , "none"
68
46
autodoc_default_options = {
69
47
"member-order" : "bysource" ,
70
48
"undoc-members" : True ,
71
49
"show-inheritance" : True ,
72
50
}
73
- autodoc_typehints = "none"
74
- always_document_param_types = False
75
- typehints_fully_qualified = True
76
51
autosectionlabel_prefix_document = True
77
52
78
53
extlinks = {
95
70
extlinks_detect_hardcoded_links = True
96
71
97
72
98
- def skip_member (app : Sphinx , what : str , name : str , obj : Any , would_skip : bool , options : Options ) -> bool : # noqa: U100
99
- return name in options .get ("exclude-members" , set ()) or would_skip
100
-
101
-
102
73
def process_signature (
103
74
app : Sphinx , # noqa: U100
104
75
objtype : str ,
@@ -113,16 +84,13 @@ def process_signature(
113
84
114
85
115
86
def setup (app : Sphinx ) -> None :
116
- logger = getLogger (__name__ )
117
-
118
- root = Path (__file__ ).parents [1 ]
119
- exe = Path (sys .executable )
87
+ here = Path (__file__ ).parent
88
+ # 1. run towncrier
89
+ root , exe = here .parent , Path (sys .executable )
120
90
towncrier = exe .with_name (f"towncrier{ exe .suffix } " )
121
91
new = check_output ([str (towncrier ), "--draft" , "--version" , "NEXT" ], cwd = root , universal_newlines = True )
122
92
(root / "docs" / "_draft.rst" ).write_text ("" if "No significant changes" in new else new )
123
93
124
- from sphinx .domains .python import PythonDomain
125
-
126
94
class PatchedPythonDomain (PythonDomain ):
127
95
def resolve_xref (
128
96
self ,
@@ -148,95 +116,10 @@ def resolve_xref(
148
116
# node.children[0].children[0] = Text(target, target)
149
117
return super ().resolve_xref (env , fromdocname , builder , type , target , node , contnode )
150
118
151
- app .connect ("autodoc-skip-member" , skip_member )
152
119
app .connect ("autodoc-process-signature" , process_signature , priority = 400 )
153
120
app .add_domain (PatchedPythonDomain , override = True )
154
-
155
- class ToxConfig (SphinxDirective ):
156
- name = "conf"
157
- has_content = True
158
- option_spec = {
159
- "keys" : unchanged_required ,
160
- "version_added" : unchanged ,
161
- "version_changed" : unchanged ,
162
- "default" : unchanged ,
163
- "constant" : flag ,
164
- "ref_suffix" : unchanged ,
165
- }
166
-
167
- def __init__ (
168
- self ,
169
- name : str ,
170
- arguments : list [str ],
171
- options : dict [str , str ],
172
- content : StringList ,
173
- lineno : int ,
174
- content_offset : int ,
175
- block_text : str ,
176
- state : RSTState ,
177
- state_machine : RSTStateMachine ,
178
- ):
179
- super ().__init__ (
180
- name ,
181
- arguments ,
182
- options ,
183
- content ,
184
- lineno ,
185
- content_offset ,
186
- block_text ,
187
- state ,
188
- state_machine ,
189
- )
190
- self ._std_domain : StandardDomain = cast (StandardDomain , self .env .get_domain ("std" ))
191
-
192
- def run (self ) -> list [Node ]:
193
- self .env .note_reread () # this document needs to be always updated
194
-
195
- line = paragraph ()
196
- line += Text ("■" if "constant" in self .options else "⚙️" )
197
- for key in (i .strip () for i in self .options ["keys" ].split ("," )):
198
- line += Text (" " )
199
- self ._mk_key (line , key )
200
- if "default" in self .options :
201
- default = self .options ["default" ]
202
- line += Text (" with default value of " )
203
- line += literal (default , default )
204
- if "version_added" in self .options :
205
- line += Text (" 📢 added in " )
206
- ver = self .options ["version_added" ]
207
- line += literal (ver , ver )
208
-
209
- p = container ("" )
210
- self .state .nested_parse (StringList (string2lines ("\n " .join (f" { i } " for i in self .content ))), 0 , p )
211
- line += p
212
-
213
- return [line ]
214
-
215
- def _mk_key (self , line : paragraph , key : str ) -> None :
216
- ref_id = key if "ref_suffix" not in self .options else f"{ key } -{ self .options ['ref_suffix' ]} "
217
- ref = reference ("" , refid = ref_id , reftitle = key )
218
- line .attributes ["ids" ].append (ref_id )
219
- st = strong ()
220
- st += literal (text = key )
221
- ref += st
222
- self ._register_ref (ref_id , ref_id , ref )
223
- line += ref
224
-
225
- def _register_ref (self , ref_name : str , ref_title : str , node : Element ) -> None :
226
- of_name , doc_name = fully_normalize_name (ref_name ), self .env .docname
227
- if of_name in self ._std_domain .labels :
228
- logger .warning (
229
- __ ("duplicate label %s, other instance in %s" ),
230
- of_name ,
231
- self .env .doc2path (self ._std_domain .labels [of_name ][0 ]),
232
- location = node ,
233
- type = "sphinx-argparse-cli" ,
234
- subtype = self .env .docname ,
235
- )
236
- self ._std_domain .anonlabels [of_name ] = doc_name , ref_name
237
- self ._std_domain .labels [of_name ] = doc_name , ref_name , ref_title
238
-
239
- app .add_directive (ToxConfig .name , ToxConfig )
121
+ tox_cfg = SourceFileLoader ("tox_conf" , str (here / "tox_conf.py" )).load_module ().ToxConfig
122
+ app .add_directive (tox_cfg .name , tox_cfg )
240
123
241
124
def check_uri (self , refnode : reference ) -> None :
242
125
if refnode .document .attributes ["source" ].endswith ("index.rst" ):
0 commit comments