Skip to content

Commit f65cf64

Browse files
authored
Merge pull request #95 from amueller/mangling_error_info
ENH: add context to section error messages Inform user about error locations, so they are easier to find.
2 parents 62cb39d + 52f247c commit f65cf64

File tree

3 files changed

+70
-8
lines changed

3 files changed

+70
-8
lines changed

numpydoc/docscrape.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,19 @@ def _parse(self):
331331
section = (s.capitalize() for s in section.split(' '))
332332
section = ' '.join(section)
333333
if self.get(section):
334-
msg = ("The section %s appears twice in the docstring." %
335-
section)
336-
raise ValueError(msg)
334+
if hasattr(self, '_obj'):
335+
# we know where the docs came from:
336+
try:
337+
filename = inspect.getsourcefile(self._obj)
338+
except TypeError:
339+
filename = None
340+
msg = ("The section %s appears twice in "
341+
"the docstring of %s in %s." %
342+
(section, self._obj, filename))
343+
raise ValueError(msg)
344+
else:
345+
msg = ("The section %s appears twice" % section)
346+
raise ValueError(msg)
337347

338348
if section in ('Parameters', 'Returns', 'Yields', 'Raises',
339349
'Warns', 'Other Parameters', 'Attributes',

numpydoc/numpydoc.py

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ def mangle_signature(app, what, name, obj, options, sig, retann):
113113

114114
if not hasattr(obj, '__doc__'):
115115
return
116-
117116
doc = SphinxDocString(pydoc.getdoc(obj))
118117
sig = doc['Signature'] or getattr(obj, '__text_signature__', None)
119118
if sig:

numpydoc/tests/test_docscrape.py

+57-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# -*- encoding:utf-8 -*-
22
from __future__ import division, absolute_import, print_function
33

4-
import sys, textwrap
5-
import io
4+
import sys
5+
import textwrap
66

77
import jinja2
88

@@ -12,8 +12,10 @@
1212
ClassDoc,
1313
ParseError
1414
)
15-
from numpydoc.docscrape_sphinx import SphinxDocString, SphinxClassDoc
16-
from nose.tools import *
15+
from numpydoc.docscrape_sphinx import (SphinxDocString, SphinxClassDoc,
16+
SphinxFunctionDoc)
17+
from nose.tools import (assert_equal, assert_raises, assert_list_equal,
18+
assert_true)
1719

1820
if sys.version_info[0] >= 3:
1921
sixu = lambda s: s
@@ -232,6 +234,55 @@ def test_section_twice():
232234
"""
233235
assert_raises(ValueError, NumpyDocString, doc_text)
234236

237+
# if we have a numpydoc object, we know where the error came from
238+
class Dummy(object):
239+
"""
240+
Dummy class.
241+
242+
Notes
243+
-----
244+
First note.
245+
246+
Notes
247+
-----
248+
Second note.
249+
250+
"""
251+
def spam(self, a, b):
252+
"""Spam\n\nSpam spam."""
253+
pass
254+
255+
def ham(self, c, d):
256+
"""Cheese\n\nNo cheese."""
257+
pass
258+
259+
def dummy_func(arg):
260+
"""
261+
Dummy function.
262+
263+
Notes
264+
-----
265+
First note.
266+
267+
Notes
268+
-----
269+
Second note.
270+
"""
271+
272+
try:
273+
SphinxClassDoc(Dummy)
274+
except ValueError as e:
275+
# python 3 version or python 2 version
276+
assert_true("test_section_twice.<locals>.Dummy" in str(e)
277+
or 'test_docscrape.Dummy' in str(e))
278+
279+
try:
280+
SphinxFunctionDoc(dummy_func)
281+
except ValueError as e:
282+
# python 3 version or python 2 version
283+
assert_true("test_section_twice.<locals>.dummy_func" in str(e)
284+
or 'function dummy_func' in str(e))
285+
235286

236287
def test_notes():
237288
assert doc['Notes'][0].startswith('Instead')
@@ -969,6 +1020,8 @@ def test_templated_sections():
9691020
""")
9701021

9711022

1023+
1024+
9721025
if __name__ == "__main__":
9731026
import nose
9741027
nose.run()

0 commit comments

Comments
 (0)