Merge branch 'add-numpydoc-support' of git://github.com/immerrr/jedi into dev

This commit is contained in:
Dave Halter
2014-07-27 11:23:39 +02:00
5 changed files with 132 additions and 29 deletions

View File

@@ -6,7 +6,7 @@ Changelog
0.8.1 (2014-07-23)
+++++++++++++++++++
* Bugfix release, the last release forgot to include files that improve
- Bugfix release, the last release forgot to include files that improve
autocompletion for builtin libraries. Fixed.
0.8.0 (2014-05-05)
@@ -16,26 +16,27 @@ Changelog
drastically. Loading times are down as well (it takes basically as long as an
import).
- REPL completion is starting to become usable.
- Various small API changes. Generally this released focuses on stability and
- Various small API changes. Generally this release focuses on stability and
refactoring of internal APIs.
- Introducing operator precedence, which makes calculating correct Array indices
and ``__getattr__`` strings possible.
- Introducing operator precedence, which makes calculating correct Array
indices and ``__getattr__`` strings possible.
0.7.0 (2013-08-09)
++++++++++++++++++
- Switched from LGPL to MIT license
- Added an Interpreter class to the API to make autocompletion in REPL possible.
- Added autocompletion support for namespace packages
- Add sith.py, a new random testing method
- Switched from LGPL to MIT license.
- Added an Interpreter class to the API to make autocompletion in REPL
possible.
- Added autocompletion support for namespace packages.
- Add sith.py, a new random testing method.
0.6.0 (2013-05-14)
++++++++++++++++++
- Much faster parser with builtin part caching
- A test suite, thanks @tkf
- Much faster parser with builtin part caching.
- A test suite, thanks @tkf.
0.5 versions (2012)
+++++++++++++++++++
- Initial development
- Initial development.

View File

@@ -119,10 +119,11 @@ http://sphinx-doc.org/domains.html#info-field-lists
::
def myfunction(node):
def myfunction(node, foo):
"""Do something with a ``node``.
:type node: ProgramNode
:param str foo: foo parameter description
"""
node.| # complete here

View File

@@ -14,6 +14,7 @@ As an addition to parameter searching, this module also provides return
annotations.
"""
from ast import literal_eval
import re
from itertools import chain
from textwrap import dedent
@@ -24,6 +25,7 @@ from jedi.common import indent_block
DOCSTRING_PARAM_PATTERNS = [
r'\s*:type\s+%s:\s*([^\n]+)', # Sphinx
r'\s*:param\s+(\w+)\s+%s:[^\n]+', # Sphinx param with type
r'\s*@type\s+%s:\s*([^\n]+)', # Epydoc
]
@@ -35,26 +37,44 @@ DOCSTRING_RETURN_PATTERNS = [
REST_ROLE_PATTERN = re.compile(r':[^`]+:`([^`]+)`')
@memoize_default(None, evaluator_is_first_arg=True)
def follow_param(evaluator, param):
func = param.parent_function
param_str = _search_param_in_docstr(func.raw_doc, str(param.get_name()))
return _evaluate_for_statement_string(evaluator, param_str, param.get_parent_until())
try:
from numpydoc.docscrape import NumpyDocString
except ImportError:
def _search_param_in_numpydocstr(docstr, param_str):
return []
else:
def _search_param_in_numpydocstr(docstr, param_str):
"""Search `docstr` (in numpydoc format) for type(-s) of `param_str`."""
params = NumpyDocString(docstr)._parsed_data['Parameters']
for p_name, p_type, p_descr in params:
if p_name == param_str:
m = re.match('([^,]+(,[^,]+)*?)(,[ ]*optional)?$', p_type)
if m:
p_type = m.group(1)
if p_type.startswith('{'):
types = set(type(x).__name__ for x in literal_eval(p_type))
return list(types)
else:
return [p_type]
return []
def _search_param_in_docstr(docstr, param_str):
"""
Search `docstr` for a type of `param_str`.
Search `docstr` for type(-s) of `param_str`.
>>> _search_param_in_docstr(':type param: int', 'param')
'int'
['int']
>>> _search_param_in_docstr('@type param: int', 'param')
'int'
['int']
>>> _search_param_in_docstr(
... ':type param: :class:`threading.Thread`', 'param')
'threading.Thread'
>>> _search_param_in_docstr('no document', 'param') is None
True
['threading.Thread']
>>> bool(_search_param_in_docstr('no document', 'param'))
False
>>> _search_param_in_docstr(':param int param: some description', 'param')
['int']
"""
# look at #40 to see definitions of those params
@@ -63,9 +83,10 @@ def _search_param_in_docstr(docstr, param_str):
for pattern in patterns:
match = pattern.search(docstr)
if match:
return _strip_rst_role(match.group(1))
return [_strip_rst_role(match.group(1))]
return None
return (_search_param_in_numpydocstr(docstr, param_str) or
[])
def _strip_rst_role(type_str):
@@ -126,6 +147,17 @@ def _evaluate_for_statement_string(evaluator, string, module):
return list(chain.from_iterable(it)) or definitions
@memoize_default(None, evaluator_is_first_arg=True)
def follow_param(evaluator, param):
func = param.parent_function
return [p
for param_str in _search_param_in_docstr(func.raw_doc,
str(param.get_name()))
for p in _evaluate_for_statement_string(evaluator, param_str,
param.get_parent_until())]
@memoize_default(None, evaluator_is_first_arg=True)
def find_return_types(evaluator, func):
def search_return_in_docstr(code):

View File

@@ -3,13 +3,14 @@
# -----------------
# sphinx style
# -----------------
def f(a, b, c, d):
def f(a, b, c, d, x):
""" asdfasdf
:param a: blablabla
:type a: str
:type b: (str, int)
:type c: threading.Thread
:type d: :class:`threading.Thread`
:param str x: blablabla
:rtype: dict
"""
#? str()
@@ -22,23 +23,28 @@ def f(a, b, c, d):
c.join
#? ['join']
d.join
#? ['lower']
x.lower
#? dict()
f()
# wrong declarations
def f(a, b):
def f(a, b, x):
"""
:param a: Forgot type declaration
:type a:
:param b: Just something
:type b: ``
:param x: Just something without type
:rtype:
"""
#?
a
#?
b
#?
x
#?
f()

View File

@@ -6,6 +6,13 @@ from textwrap import dedent
import jedi
from ..helpers import unittest
try:
import numpydoc
except ImportError:
numpydoc_unavailable = True
else:
numpydoc_unavailable = False
class TestDocstring(unittest.TestCase):
def test_function_doc(self):
@@ -50,6 +57,16 @@ class TestDocstring(unittest.TestCase):
names = [c.name for c in jedi.Script(s).completions()]
assert 'start' in names
def test_docstrings_param_type(self):
s = """
def func(arg):
'''
:param str arg: some description
'''
arg."""
names = [c.name for c in jedi.Script(s).completions()]
assert 'join' in names
def test_docstrings_type_str(self):
s = """
def func(arg):
@@ -87,3 +104,49 @@ class TestDocstring(unittest.TestCase):
assert 'a' in names
assert '__init__' in names
assert 'mro' not in names # Exists only for types.
@unittest.skipIf(numpydoc_unavailable, 'numpydoc module is unavailable')
def test_numpydoc_docstring(self):
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : int
y : str
"""
y.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
@unittest.skipIf(numpydoc_unavailable, 'numpydoc module is unavailable')
def test_numpydoc_docstring_set_of_values(self):
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : {'foo', 'bar', 100500}, optional
"""
x.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
@unittest.skipIf(numpydoc_unavailable, 'numpydoc module is unavailable')
def test_numpydoc_alternative_types(self):
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : int or str or list
"""
x.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
assert 'append' in names