mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
dostring fixes.
This commit is contained in:
@@ -26,7 +26,7 @@ class Context(object):
|
|||||||
return context
|
return context
|
||||||
context = context.parent_context
|
context = context.parent_context
|
||||||
|
|
||||||
def execute(self, arguments=None):
|
def execute(self, arguments):
|
||||||
return self.evaluator.execute(self, arguments)
|
return self.evaluator.execute(self, arguments)
|
||||||
|
|
||||||
def execute_evaluated(self, *value_list):
|
def execute_evaluated(self, *value_list):
|
||||||
|
|||||||
@@ -16,12 +16,14 @@ annotations.
|
|||||||
|
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
import re
|
import re
|
||||||
from itertools import chain
|
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
|
from jedi._compatibility import u
|
||||||
|
from jedi.common import unite
|
||||||
|
from jedi.evaluate import context
|
||||||
from jedi.evaluate.cache import memoize_default
|
from jedi.evaluate.cache import memoize_default
|
||||||
from jedi.parser import ParserWithRecovery, load_grammar
|
from jedi.parser import ParserWithRecovery, load_grammar
|
||||||
from jedi.parser.tree import Class
|
from jedi.parser.tree import search_ancestor
|
||||||
from jedi.common import indent_block
|
from jedi.common import indent_block
|
||||||
from jedi.evaluate.iterable import ArrayLiteralContext, FakeSequence, AlreadyEvaluated
|
from jedi.evaluate.iterable import ArrayLiteralContext, FakeSequence, AlreadyEvaluated
|
||||||
|
|
||||||
@@ -114,12 +116,12 @@ def _strip_rst_role(type_str):
|
|||||||
return type_str
|
return type_str
|
||||||
|
|
||||||
|
|
||||||
def _evaluate_for_statement_string(evaluator, string, module):
|
def _evaluate_for_statement_string(module_context, string):
|
||||||
code = dedent("""
|
code = dedent(u("""
|
||||||
def pseudo_docstring_stuff():
|
def pseudo_docstring_stuff():
|
||||||
# Create a pseudo function for docstring statements.
|
# Create a pseudo function for docstring statements.
|
||||||
%s
|
{0}
|
||||||
""")
|
"""))
|
||||||
if string is None:
|
if string is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@@ -131,31 +133,39 @@ def _evaluate_for_statement_string(evaluator, string, module):
|
|||||||
# Take the default grammar here, if we load the Python 2.7 grammar here, it
|
# Take the default grammar here, if we load the Python 2.7 grammar here, it
|
||||||
# will be impossible to use `...` (Ellipsis) as a token. Docstring types
|
# will be impossible to use `...` (Ellipsis) as a token. Docstring types
|
||||||
# don't need to conform with the current grammar.
|
# don't need to conform with the current grammar.
|
||||||
p = ParserWithRecovery(load_grammar(), code % indent_block(string))
|
p = ParserWithRecovery(load_grammar(), code.format(indent_block(string)))
|
||||||
try:
|
try:
|
||||||
pseudo_cls = p.module.subscopes[0]
|
funcdef = p.module.subscopes[0]
|
||||||
# First pick suite, then simple_stmt and then the node,
|
# First pick suite, then simple_stmt and then the node,
|
||||||
# which is also not the last item, because there's a newline.
|
# which is also not the last item, because there's a newline.
|
||||||
stmt = pseudo_cls.children[-1].children[-1].children[-2]
|
stmt = funcdef.children[-1].children[-1].children[-2]
|
||||||
except (AttributeError, IndexError):
|
except (AttributeError, IndexError):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
from jedi.evaluate.param import ValuesArguments
|
||||||
|
from jedi.evaluate.representation import FunctionExecutionContext
|
||||||
|
func_context = FunctionExecutionContext(
|
||||||
|
module_context.evaluator,
|
||||||
|
module_context,
|
||||||
|
funcdef,
|
||||||
|
ValuesArguments([])
|
||||||
|
)
|
||||||
|
|
||||||
# Use the module of the param.
|
# Use the module of the param.
|
||||||
# TODO this module is not the module of the param in case of a function
|
# TODO this module is not the module of the param in case of a function
|
||||||
# call. In that case it's the module of the function call.
|
# call. In that case it's the module of the function call.
|
||||||
# stuffed with content from a function call.
|
# stuffed with content from a function call.
|
||||||
pseudo_cls.parent = module
|
return list(_execute_types_in_stmt(func_context, stmt))
|
||||||
return list(_execute_types_in_stmt(evaluator, stmt))
|
|
||||||
|
|
||||||
|
|
||||||
def _execute_types_in_stmt(evaluator, stmt):
|
def _execute_types_in_stmt(module_context, stmt):
|
||||||
"""
|
"""
|
||||||
Executing all types or general elements that we find in a statement. This
|
Executing all types or general elements that we find in a statement. This
|
||||||
doesn't include tuple, list and dict literals, because the stuff they
|
doesn't include tuple, list and dict literals, because the stuff they
|
||||||
contain is executed. (Used as type information).
|
contain is executed. (Used as type information).
|
||||||
"""
|
"""
|
||||||
definitions = evaluator.eval_element(stmt)
|
definitions = module_context.eval_node(stmt)
|
||||||
return chain.from_iterable(_execute_array_values(evaluator, d) for d in definitions)
|
return unite(_execute_array_values(module_context.evaluator, d) for d in definitions)
|
||||||
|
|
||||||
|
|
||||||
def _execute_array_values(evaluator, array):
|
def _execute_array_values(evaluator, array):
|
||||||
@@ -165,35 +175,33 @@ def _execute_array_values(evaluator, array):
|
|||||||
"""
|
"""
|
||||||
if isinstance(array, ArrayLiteralContext):
|
if isinstance(array, ArrayLiteralContext):
|
||||||
values = []
|
values = []
|
||||||
for types in array.py__iter__():
|
for lazy_context in array.py__iter__():
|
||||||
objects = set(chain.from_iterable(_execute_array_values(evaluator, typ) for typ in types))
|
objects = unite(_execute_array_values(evaluator, typ) for typ in lazy_context.infer())
|
||||||
values.append(AlreadyEvaluated(objects))
|
values.append(context.LazyKnownContexts(objects))
|
||||||
return [FakeSequence(evaluator, values, array.type)]
|
return set([FakeSequence(evaluator, array.array_type, values)])
|
||||||
else:
|
else:
|
||||||
return evaluator.execute(array)
|
return array.execute_evaluated()
|
||||||
|
|
||||||
|
|
||||||
@memoize_default(None, evaluator_is_first_arg=True)
|
@memoize_default()
|
||||||
def follow_param(evaluator, param):
|
def follow_param(module_context, param):
|
||||||
def eval_docstring(docstring):
|
def eval_docstring(docstring):
|
||||||
return set(
|
return set(
|
||||||
[p for param_str in _search_param_in_docstr(docstring, str(param.name))
|
[p for param_str in _search_param_in_docstr(docstring, str(param.name))
|
||||||
for p in _evaluate_for_statement_string(evaluator, param_str, module)]
|
for p in _evaluate_for_statement_string(module_context, param_str)]
|
||||||
)
|
)
|
||||||
func = param.parent_function
|
func = param.parent_function
|
||||||
module = param.get_parent_until()
|
|
||||||
|
|
||||||
types = eval_docstring(func.raw_doc)
|
types = eval_docstring(func.raw_doc)
|
||||||
if func.name.value == '__init__':
|
if func.name.value == '__init__':
|
||||||
cls = func.get_parent_until(Class)
|
cls = search_ancestor(func, 'classdef')
|
||||||
if cls.type == 'classdef':
|
if cls.type == 'classdef':
|
||||||
types |= eval_docstring(cls.raw_doc)
|
types |= eval_docstring(cls.raw_doc)
|
||||||
|
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
@memoize_default(None, evaluator_is_first_arg=True)
|
@memoize_default()
|
||||||
def find_return_types(evaluator, func):
|
def find_return_types(module_context, func):
|
||||||
def search_return_in_docstr(code):
|
def search_return_in_docstr(code):
|
||||||
for p in DOCSTRING_RETURN_PATTERNS:
|
for p in DOCSTRING_RETURN_PATTERNS:
|
||||||
match = p.search(code)
|
match = p.search(code)
|
||||||
@@ -201,4 +209,4 @@ def find_return_types(evaluator, func):
|
|||||||
return _strip_rst_role(match.group(1))
|
return _strip_rst_role(match.group(1))
|
||||||
|
|
||||||
type_str = search_return_in_docstr(func.raw_doc)
|
type_str = search_return_in_docstr(func.raw_doc)
|
||||||
return _evaluate_for_statement_string(evaluator, type_str, func.get_parent_until())
|
return _evaluate_for_statement_string(module_context, type_str)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from jedi.parser import tree
|
|||||||
from jedi.evaluate import iterable
|
from jedi.evaluate import iterable
|
||||||
from jedi.evaluate import analysis
|
from jedi.evaluate import analysis
|
||||||
from jedi.evaluate import context
|
from jedi.evaluate import context
|
||||||
|
from jedi.evaluate import docstrings
|
||||||
|
|
||||||
|
|
||||||
def try_iter_content(types, depth=0):
|
def try_iter_content(types, depth=0):
|
||||||
@@ -175,13 +176,19 @@ class ValuesArguments(AbstractArguments):
|
|||||||
|
|
||||||
class ExecutedParam(object):
|
class ExecutedParam(object):
|
||||||
"""Fake a param and give it values."""
|
"""Fake a param and give it values."""
|
||||||
def __init__(self, original_param, var_args, lazy_context):
|
def __init__(self, var_args_context, original_param, var_args, lazy_context):
|
||||||
|
self._root_context = var_args_context.get_root_context()
|
||||||
self._original_param = original_param
|
self._original_param = original_param
|
||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
self._lazy_context = lazy_context
|
self._lazy_context = lazy_context
|
||||||
self.string_name = self._original_param.name.value
|
self.string_name = self._original_param.name.value
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
|
pep0484_hints = set()#pep0484.follow_param(evaluator, param)
|
||||||
|
doc_params = docstrings.follow_param(self._root_context, self._original_param)
|
||||||
|
if pep0484_hints or doc_params:
|
||||||
|
return list(set(pep0484_hints) | set(doc_params))
|
||||||
|
|
||||||
return self._lazy_context.infer()
|
return self._lazy_context.infer()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -253,7 +260,7 @@ def get_params(evaluator, parent_context, func, var_args):
|
|||||||
analysis.add(evaluator, 'type-error-multiple-values',
|
analysis.add(evaluator, 'type-error-multiple-values',
|
||||||
calling_va, message=m)
|
calling_va, message=m)
|
||||||
else:
|
else:
|
||||||
keys_used[key] = ExecutedParam(key_param, var_args, argument)
|
keys_used[key] = ExecutedParam(parent_context, key_param, var_args, argument)
|
||||||
key, argument = next(var_arg_iterator, (None, None))
|
key, argument = next(var_arg_iterator, (None, None))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -297,7 +304,7 @@ def get_params(evaluator, parent_context, func, var_args):
|
|||||||
else:
|
else:
|
||||||
result_arg = argument
|
result_arg = argument
|
||||||
|
|
||||||
result_params.append(ExecutedParam(param, var_args, result_arg))
|
result_params.append(ExecutedParam(parent_context, param, var_args, result_arg))
|
||||||
keys_used[param.name.value] = result_params[-1]
|
keys_used[param.name.value] = result_params[-1]
|
||||||
|
|
||||||
if keys_only:
|
if keys_only:
|
||||||
@@ -403,4 +410,4 @@ def create_default_param(parent_context, param):
|
|||||||
result_arg = context.LazyUnknownContext()
|
result_arg = context.LazyUnknownContext()
|
||||||
else:
|
else:
|
||||||
result_arg = context.LazyTreeContext(parent_context, param.default)
|
result_arg = context.LazyTreeContext(parent_context, param.default)
|
||||||
return ExecutedParam(param, None, result_arg)
|
return ExecutedParam(parent_context, param, None, result_arg)
|
||||||
|
|||||||
@@ -643,7 +643,7 @@ class FunctionExecutionContext(Executed):
|
|||||||
returns = funcdef.yields
|
returns = funcdef.yields
|
||||||
else:
|
else:
|
||||||
returns = funcdef.returns
|
returns = funcdef.returns
|
||||||
types = set(docstrings.find_return_types(self.evaluator, funcdef))
|
types = set(docstrings.find_return_types(self.get_root_context(), funcdef))
|
||||||
types |= set(pep0484.find_return_types(self.evaluator, funcdef))
|
types |= set(pep0484.find_return_types(self.evaluator, funcdef))
|
||||||
|
|
||||||
for r in returns:
|
for r in returns:
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ from jedi import debug
|
|||||||
from jedi._compatibility import unicode, is_py3
|
from jedi._compatibility import unicode, is_py3
|
||||||
from jedi.parser import Parser, load_grammar
|
from jedi.parser import Parser, load_grammar
|
||||||
from jedi.api.classes import Definition
|
from jedi.api.classes import Definition
|
||||||
|
from jedi.api.completion import get_user_scope
|
||||||
from jedi.evaluate.representation import ModuleContext
|
from jedi.evaluate.representation import ModuleContext
|
||||||
|
|
||||||
|
|
||||||
@@ -193,7 +194,8 @@ class IntegrationTestCase(object):
|
|||||||
module_context = script._get_module()
|
module_context = script._get_module()
|
||||||
# The context shouldn't matter for the test results.
|
# The context shouldn't matter for the test results.
|
||||||
element.parent = module_context.module_node
|
element.parent = module_context.module_node
|
||||||
results = evaluator.eval_element(module_context, element)
|
user_context = get_user_scope(module_context, (self.line_nr, 0))
|
||||||
|
results = evaluator.eval_element(user_context, element)
|
||||||
if not results:
|
if not results:
|
||||||
raise Exception('Could not resolve %s on line %s'
|
raise Exception('Could not resolve %s on line %s'
|
||||||
% (match.string, self.line_nr - 1))
|
% (match.string, self.line_nr - 1))
|
||||||
|
|||||||
Reference in New Issue
Block a user