6
6
from sphinx .util .osutil import copyfile
7
7
from sphinx .util .console import bold
8
8
from sphinx .domains .python import PyXRefRole
9
+ from sphinx .domains .python import PythonDomain
10
+
11
+ # the searchindex.js system relies upon the object types
12
+ # in the PythonDomain to create search entries
13
+ from sphinx .domains import ObjType
14
+
15
+ PythonDomain .object_types ['parameter' ] = ObjType ('parameter' , 'param' )
16
+
9
17
10
18
def _is_html (app ):
11
- return app .builder .name in ('html' , 'readthedocs' ) # 'readthedocs', classy
19
+ return app .builder .name in ('html' , 'readthedocs' )
20
+
21
+
22
+ def _tempdata (app ):
23
+ if '_sphinx_paramlinks_index' in app .env .indexentries :
24
+ idx = app .env .indexentries ['_sphinx_paramlinks_index' ]
25
+ else :
26
+ app .env .indexentries ['_sphinx_paramlinks_index' ] = idx = {}
27
+ return idx
28
+
12
29
13
30
def autodoc_process_docstring (app , what , name , obj , options , lines ):
14
31
# locate :param: lines within docstrings. augment the parameter
15
32
# name with that of the parent object name plus a token we can
16
- # spot later.
33
+ # spot later. Also put an index entry in a temporary collection.
34
+
35
+ idx = _tempdata (app )
36
+
37
+ docname = app .env .temp_data ['docname' ]
38
+ if docname in idx :
39
+ doc_idx = idx [docname ]
40
+ else :
41
+ idx [docname ] = doc_idx = []
42
+
17
43
def _cvt_param (name , line ):
18
44
if name .endswith (".__init__" ):
19
45
# kill off __init__ if present, the links are always
20
46
# off the class
21
47
name = name [0 :- 9 ]
48
+
22
49
def cvt (m ):
50
+ modifier , objname , paramname = m .group (1 ) or '' , name , m .group (2 )
51
+ doc_idx .append (
52
+ ('single' , '%s (%s parameter)' % (paramname , objname ),
53
+ '%s.params.%s' % (objname , paramname ), '' )
54
+ )
55
+
23
56
return ":param %s_sphinx_paramlinks_%s.%s:" % (
24
- m . group ( 1 ) or '' , name , m . group ( 2 ) )
57
+ modifier , objname , paramname )
25
58
return re .sub (r'^:param ([^:]+? )?([^:]+?):' , cvt , line )
26
59
27
60
if what in ('function' , 'method' , 'class' ):
28
61
lines [:] = [_cvt_param (name , line ) for line in lines ]
29
62
63
+
30
64
class LinkParams (Transform ):
31
65
# apply references targets and optional references
32
66
# to nodes that contain our target text.
@@ -52,7 +86,8 @@ def apply(self):
52
86
refname = eq_match .group (1 )
53
87
54
88
refid = "%s.params.%s" % (location , refname )
55
- ref .parent .insert (0 ,
89
+ ref .parent .insert (
90
+ 0 ,
56
91
nodes .target ('' , '' , ids = [refid ])
57
92
)
58
93
del ref [0 ]
@@ -77,23 +112,26 @@ def apply(self):
77
112
78
113
for pos , node in enumerate (ref .parent .children ):
79
114
# try to figure out where the node with the
80
- # paramname is. thought this was simple, but readthedocs
81
- # proving..it's not.
115
+ # paramname is. thought this was simple, but
116
+ # readthedocs proving..it's not.
82
117
# TODO: need to take into account a type name
83
118
# with the parens.
84
- if isinstance (node , nodes .TextElement ) and node .astext () == paramname :
119
+ if isinstance (node , nodes .TextElement ) and \
120
+ node .astext () == paramname :
85
121
break
86
122
else :
87
123
return
88
124
89
- ref .parent .insert (pos + 1 ,
90
- nodes .reference ('' , '' ,
91
- nodes .Text (u"¶" , u"¶" ),
92
- refid = refid ,
93
- # paramlink is our own CSS class, headerlink
94
- # is theirs. Trying to get everything we can for existing
95
- # symbols...
96
- classes = ['paramlink' , 'headerlink' ]
125
+ ref .parent .insert (
126
+ pos + 1 ,
127
+ nodes .reference (
128
+ '' , '' ,
129
+ nodes .Text (u"¶" , u"¶" ),
130
+ refid = refid ,
131
+ # paramlink is our own CSS class, headerlink
132
+ # is theirs. Trying to get everything we can for
133
+ # existing symbols...
134
+ classes = ['paramlink' , 'headerlink' ]
97
135
)
98
136
)
99
137
@@ -114,7 +152,8 @@ def lookup_params(app, env, node, contnode):
114
152
resolve_target = "." .join (tokens [0 :- 1 ])
115
153
paramname = tokens [- 1 ]
116
154
117
- # emulate the approach within sphinx.environment.BuildEnvironment.resolve_references
155
+ # emulate the approach within
156
+ # sphinx.environment.BuildEnvironment.resolve_references
118
157
try :
119
158
domain = env .domains [node ['refdomain' ]] # hint: this will be 'py'
120
159
except KeyError :
@@ -130,8 +169,9 @@ def lookup_params(app, env, node, contnode):
130
169
# along with the classname/methodname/funcname minus the parameter
131
170
# part.
132
171
133
- newnode = domain .resolve_xref (env , refdoc , app .builder ,
134
- "obj" , resolve_target , node , contnode )
172
+ newnode = domain .resolve_xref (
173
+ env , refdoc , app .builder ,
174
+ "obj" , resolve_target , node , contnode )
135
175
136
176
if newnode is not None :
137
177
# assuming we found it, tack the paramname back onto to the final
@@ -142,11 +182,14 @@ def lookup_params(app, env, node, contnode):
142
182
newnode ['refid' ] += ".params." + paramname
143
183
return newnode
144
184
185
+
145
186
def add_stylesheet (app ):
146
187
app .add_stylesheet ('sphinx_paramlinks.css' )
147
188
189
+
148
190
def copy_stylesheet (app , exception ):
149
- app .info (bold ('The name of the builder is: %s' % app .builder .name ), nonl = True )
191
+ app .info (
192
+ bold ('The name of the builder is: %s' % app .builder .name ), nonl = True )
150
193
151
194
if not _is_html (app ) or exception :
152
195
return
@@ -162,6 +205,20 @@ def copy_stylesheet(app, exception):
162
205
copyfile (os .path .join (source , "sphinx_paramlinks.css" ), dest )
163
206
app .info ('done' )
164
207
208
+
209
+ def build_index (app , doctree ):
210
+ entries = _tempdata (app )
211
+
212
+ for docname in entries :
213
+ doc_entries = entries [docname ]
214
+ app .env .indexentries [docname ].extend (doc_entries )
215
+
216
+ for sing , desc , ref , extra in doc_entries :
217
+ app .env .domains ['py' ].data ['objects' ][ref ] = (docname , 'parameter' )
218
+
219
+ app .env .indexentries .pop ('_sphinx_paramlinks_index' )
220
+
221
+
165
222
def setup (app ):
166
223
app .add_transform (LinkParams )
167
224
@@ -174,4 +231,4 @@ def setup(app):
174
231
app .connect ('builder-inited' , add_stylesheet )
175
232
app .connect ('build-finished' , copy_stylesheet )
176
233
app .connect ('missing-reference' , lookup_params )
177
-
234
+ app . connect ( 'doctree-read' , build_index )
0 commit comments