Skip to content

Commit

Permalink
Add py__doc__ as a better approach to docstrings.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhalter committed Apr 20, 2017
1 parent b4631d6 commit 7ca6257
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 38 deletions.
45 changes: 16 additions & 29 deletions jedi/api/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
from jedi.evaluate import instance
from jedi.evaluate import imports
from jedi.evaluate import compiled
from jedi.evaluate.filters import ParamName
from jedi.evaluate.filters import ParamName, TreeNameDefinition
from jedi.evaluate.imports import ImportName
from jedi.api.keywords import KeywordName
from jedi.parser_utils import clean_scope_docstring, get_doc_with_call_signature


def _sort_names_by_start_pos(names):
Expand Down Expand Up @@ -255,7 +255,7 @@ def doc(self):
.. todo:: Remove!
"""
warnings.warn("Use docstring() instead.", DeprecationWarning)
return self.docstring()
return self.docstring(raw=False)

@property
def raw_doc(self):
Expand Down Expand Up @@ -469,7 +469,7 @@ def docstring(self, raw=False, fast=True):
# In this case we can just resolve the like name, because we
# wouldn't load like > 100 Python modules anymore.
fast = False
return super(Completion, self,).docstring(raw, fast)
return super(Completion, self).docstring(raw=raw, fast=fast)

@property
def description(self):
Expand Down Expand Up @@ -698,37 +698,24 @@ def __init__(self, definition):
self._name = definition

@memoize_method
def _get_node(self, fast):
if isinstance(self._name, (compiled.CompiledContextName, compiled.CompiledName)):
followed = self._name.infer()
if followed:
return next(iter(followed))
return None
def _get_contexts(self, fast):
if isinstance(self._name, ImportName) and fast:
return {}

if self._name.api_type == 'module' and not fast:
followed = self._name.infer()
if followed:
# TODO: Use all of the followed objects as input to Documentation.
context = next(iter(followed))
return context.tree_node
if self._name.tree_name is None:
return None
return self._name.tree_name.get_definition()
if self._name.api_type == 'statement':
return {}

return self._name.infer()

def docstring(self, fast=True, raw=True):
"""
The docstring ``__doc__`` for any object.
See :attr:`doc` for example.
"""
node = self._get_node(fast)
# TODO: Use all of the followed objects as output. Possibly divinding
# them by a few dashes.
for context in self._get_contexts(fast=fast):
return context.py__doc__(include_call_signature=not raw)

try:
node.get_doc_node
except AttributeError:
return ''
else:
if raw:
return clean_scope_docstring(node)
else:
return get_doc_with_call_signature(node)
return ''
8 changes: 4 additions & 4 deletions jedi/evaluate/compiled/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ def py__file__(self):
def is_class(self):
return inspect.isclass(self.obj)

@property
def doc(self):
def py__doc__(self, include_call_signature=False):
return inspect.getdoc(self.obj) or ''

@property
Expand Down Expand Up @@ -129,10 +128,11 @@ def __repr__(self):

@underscore_memoization
def _parse_function_doc(self):
if self.doc is None:
doc = self.py__doc__()
if doc is None:
return '', ''

return _parse_function_doc(self.doc)
return _parse_function_doc(doc)

@property
def api_type(self):
Expand Down
13 changes: 13 additions & 0 deletions jedi/evaluate/context.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from jedi._compatibility import Python3Method
from jedi.common import unite
from jedi.parser.python.tree import ExprStmt, CompFor
from jedi.parser_utils import clean_scope_docstring, get_doc_with_call_signature


class Context(object):
Expand Down Expand Up @@ -63,6 +64,18 @@ def py__bool__(self):
"""
return True

def py__doc__(self, include_call_signature=False):
try:
self.tree_node.get_doc_node
except AttributeError:
return ''
else:
if include_call_signature:
return get_doc_with_call_signature(self.tree_node)
else:
return clean_scope_docstring(self.tree_node)
return None


class TreeContext(Context):
def __init__(self, evaluator, parent_context=None):
Expand Down
2 changes: 2 additions & 0 deletions jedi/evaluate/representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
py__path__() Only on modules. For the import system.
py__get__(call_object) Only on instances. Simulates
descriptors.
py__doc__(include_call_signature: Returns the docstring for a context.
bool)
====================================== ========================================
"""
Expand Down
24 changes: 20 additions & 4 deletions test/test_api/test_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,27 @@ def docstr(src, result):
docstr('import jedi\njedi.Scr', cleandoc(Script.__doc__))

docstr('abcd=3;abcd', '')
docstr('"hello"\nabcd=3\nabcd', 'hello')
# It works with a ; as well.
docstr('"hello"\nabcd=3;abcd', 'hello')
docstr('"hello"\nabcd=3\nabcd', '')
docstr(dedent('''
def x():
"hello"
0
x'''),
'hello'
)
docstr(dedent('''
def x():
"hello";0
x'''),
'hello'
)
# Shouldn't work with a tuple.
docstr('"hello",0\nabcd=3\nabcd', '')
docstr(dedent('''
def x():
"hello",0
x'''),
''
)


def test_completion_params():
Expand Down
2 changes: 1 addition & 1 deletion test/test_evaluate/test_compiled.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_doc():
just a Jedi API definition.
"""
obj = compiled.CompiledObject(_evaluator(), ''.__getnewargs__)
assert obj.doc == ''
assert obj.py__doc__() == ''


def test_string_literals():
Expand Down

0 comments on commit 7ca6257

Please sign in to comment.