@@ -173,6 +173,9 @@ def _strip(self, doc):
173
173
174
174
return doc [i :len (doc )- j ]
175
175
176
+ def _get_line_no (self ):
177
+ return self ._doc ._l
178
+
176
179
def _read_to_next_section (self ):
177
180
section = self ._doc .read_to_next_empty_line ()
178
181
@@ -186,20 +189,22 @@ def _read_to_next_section(self):
186
189
187
190
def _read_sections (self ):
188
191
while not self ._doc .eof ():
192
+ start = self ._get_line_no ()
189
193
data = self ._read_to_next_section ()
190
194
name = data [0 ].strip ()
191
195
192
196
if name .startswith ('..' ): # index section
193
- yield name , data [1 :]
197
+ yield name , data [1 :], ( start , len ( data ))
194
198
elif len (data ) < 2 :
195
199
yield StopIteration
196
200
else :
197
- yield name , self ._strip (data [2 :])
201
+ yield name , self ._strip (data [2 :]), ( start , len ( data ))
198
202
199
203
def _parse_param_list (self , content ):
200
204
r = Reader (content )
201
205
params = []
202
206
while not r .eof ():
207
+ start = r ._l
203
208
header = r .read ().strip ()
204
209
if ' : ' in header :
205
210
arg_name , arg_type = header .split (' : ' )[:2 ]
@@ -209,7 +214,7 @@ def _parse_param_list(self, content):
209
214
desc = r .read_to_next_unindented_line ()
210
215
desc = dedent_lines (desc )
211
216
212
- params .append ((arg_name , arg_type , desc ))
217
+ params .append ((arg_name , arg_type , desc , ( start , len ( desc ) + 1 ) ))
213
218
214
219
return params
215
220
@@ -315,9 +320,10 @@ def _parse_summary(self):
315
320
def _parse (self ):
316
321
self ._doc .reset ()
317
322
self ._parse_summary ()
323
+ self ._line_spans = {}
318
324
319
325
sections = list (self ._read_sections ())
320
- section_names = set ([section for section , content in sections ])
326
+ section_names = set ([section for section , content , span in sections ])
321
327
322
328
has_returns = 'Returns' in section_names
323
329
has_yields = 'Yields' in section_names
@@ -326,7 +332,7 @@ def _parse(self):
326
332
msg = 'Docstring contains both a Returns and Yields section.'
327
333
raise ValueError (msg )
328
334
329
- for (section , content ) in sections :
335
+ for (section , content , span ) in sections :
330
336
if not section .startswith ('..' ):
331
337
section = (s .capitalize () for s in section .split (' ' ))
332
338
section = ' ' .join (section )
@@ -335,10 +341,19 @@ def _parse(self):
335
341
section )
336
342
raise ValueError (msg )
337
343
344
+ self ._line_spans [section ] = span
345
+ section_start = span [0 ] + 2
346
+
338
347
if section in ('Parameters' , 'Returns' , 'Yields' , 'Raises' ,
339
348
'Warns' , 'Other Parameters' , 'Attributes' ,
340
349
'Methods' ):
341
- self [section ] = self ._parse_param_list (content )
350
+ param_list = []
351
+ for i , param in enumerate (self ._parse_param_list (content )):
352
+ span = param [- 1 ]
353
+ span = (span [0 ] + section_start , span [1 ])
354
+ self ._line_spans [section , i ] = span
355
+ param_list .append (param [:- 1 ])
356
+ self [section ] = param_list
342
357
elif section .startswith ('.. index::' ):
343
358
self ['index' ] = self ._parse_index (section , content )
344
359
elif section == 'See Also' :
0 commit comments