From fc785ce6ea8c889ef2b6d6369312e24bf40e8ac0 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 22 Dec 2019 02:05:02 +0100 Subject: [PATCH] Attribute docstrings work now, fixes #138 --- jedi/inference/names.py | 7 ++++--- jedi/parser_utils.py | 15 +++++++++++++++ test/test_api/test_documentation.py | 23 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/jedi/inference/names.py b/jedi/inference/names.py index 3a830b1e2..9335c4463 100644 --- a/jedi/inference/names.py +++ b/jedi/inference/names.py @@ -3,7 +3,7 @@ from parso.tree import search_ancestor from jedi._compatibility import Parameter -from jedi.parser_utils import clean_scope_docstring +from jedi.parser_utils import clean_scope_docstring, find_statement_documentation from jedi.inference.utils import unite from jedi.inference.base_value import ValueSet, NO_VALUES from jedi.inference import docstrings @@ -324,10 +324,12 @@ def py__doc__(self, include_signatures=False): if self.api_type in ('function', 'class'): return clean_scope_docstring(self.tree_name.get_definition()) + if self.api_type == 'statement' and self.tree_name.is_definition(): + return find_statement_documentation(self.tree_name.get_definition()) + if self.api_type == 'module': names = self.goto() if self not in names: - print('la', _merge_name_docs(names)) return _merge_name_docs(names) return super(TreeNameDefinition, self).py__doc__(include_signatures) @@ -578,7 +580,6 @@ def api_type(self): return 'module' def py__doc__(self, include_signatures=False): - print('la', (self.goto())) return _merge_name_docs(self.goto()) diff --git a/jedi/parser_utils.py b/jedi/parser_utils.py index 5667853f2..8b939fef2 100644 --- a/jedi/parser_utils.py +++ b/jedi/parser_utils.py @@ -109,6 +109,21 @@ def clean_scope_docstring(scope_node): return '' +def find_statement_documentation(tree_node): + if tree_node.type == 'expr_stmt': + tree_node = tree_node.parent # simple_stmt + maybe_string = tree_node.get_next_sibling() + if maybe_string is not None: + if maybe_string.type == 'simple_stmt': + maybe_string = maybe_string.children[0] + if maybe_string.type == 'string': + cleaned = cleandoc(safe_literal_eval(maybe_string.value)) + # Since we want the docstr output to be always unicode, just + # force it. + return force_unicode(cleaned) + return '' + + def safe_literal_eval(value): first_two = value[:2].lower() if first_two[0] == 'f' or first_two in ('fr', 'rf'): diff --git a/test/test_api/test_documentation.py b/test/test_api/test_documentation.py index 7e8ac5c96..9974d6aca 100644 --- a/test/test_api/test_documentation.py +++ b/test/test_api/test_documentation.py @@ -52,3 +52,26 @@ def test_lambda(Script): ) def test_help_no_returns(Script, code, kwargs): assert not Script(code).help(**kwargs) + + +def test_attribute_docstrings(goto_or_help): + code = dedent('''\ + class X: + "ha" + x = 3 + """ Yeah """ + y = 5 + "f g " + z = lambda: 1 + ''') + + d, = goto_or_help(code + 'X.x') + assert d.docstring() == 'Yeah ' + d, = goto_or_help(code + 'X().x') + assert d.docstring() == 'Yeah ' + + d, = goto_or_help(code + 'X.y') + assert d.docstring() == 'f g ' + + d, = goto_or_help(code + 'X.z') + assert d.docstring() == ''