A lot more fixes - fix all evaluate integration tests.

This commit is contained in:
Dave Halter
2016-12-03 22:17:38 +01:00
parent ee1f077014
commit 6940900c58
10 changed files with 91 additions and 53 deletions

View File

@@ -216,11 +216,9 @@ class Script(object):
"""
def filter_follow_imports(names):
for name in names:
definition = name.get_definition()
if definition.type in ('import_name', 'import_from'):
imp = imports.ImportWrapper(context, name)
for name in filter_follow_imports(imp.follow(is_goto=True)):
yield name
if isinstance(name, (imports.ImportName, TreeNameDefinition)):
for context in name.infer():
yield context.name
else:
yield name
@@ -436,13 +434,21 @@ def names(source=None, path=None, encoding='utf-8', all_scopes=False,
``definitions=True``. E.g. ``a = b`` returns ``b``.
"""
def def_ref_filter(_def):
is_def = _def.is_definition()
is_def = _def._name.tree_name.is_definition()
return definitions and is_def or references and not is_def
# Set line/column to a random position, because they don't matter.
script = Script(source, line=1, column=0, path=path, encoding=encoding)
defs = [classes.Definition(script._evaluator, name_part)
for name_part in get_module_names(script._get_module().module_node, all_scopes)]
module_context = script._get_module()
defs = [
classes.Definition(
script._evaluator,
TreeNameDefinition(
module_context.create_context(name),
name
)
) for name in get_module_names(script._get_module_node(), all_scopes)
]
return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column))

View File

@@ -18,7 +18,9 @@ from jedi.evaluate import instance
from jedi.evaluate import iterable
from jedi.evaluate import imports
from jedi.evaluate import compiled
from jedi.evaluate.filters import ParamName
from jedi.evaluate.finder import filter_definition_names
from jedi.api.keywords import KeywordName
def defined_names(evaluator, scope):
@@ -63,7 +65,7 @@ class BaseDefinition(object):
An instance of :class:`jedi.parser.reprsentation.Name` subclass.
"""
#self._definition = list(self._name.infer())[0]
#self.is_keyword = isinstance(self._definition, keywords.Keyword)
self.is_keyword = isinstance(self._name, KeywordName)
self._definition = None
# generate a path to the definition
@@ -232,9 +234,9 @@ class BaseDefinition(object):
"""
if raw:
return _Help(self._definition).raw()
return _Help(self._name.parent_context).raw()
else:
return _Help(self._definition).full()
return _Help(self._name.parent_context).full()
@property
def doc(self):
@@ -259,7 +261,7 @@ class BaseDefinition(object):
@property
def description(self):
"""A textual description of the object."""
return unicode(self._name)
return unicode(self._name.string_name)
@property
def full_name(self):
@@ -298,7 +300,12 @@ class BaseDefinition(object):
return '.'.join(path if path[0] else path[1:])
def goto_assignments(self):
defs = self._evaluator.goto(self._name)
try:
tree_name = self._name.tree_name
except AttributeError:
return self
defs = self._evaluator.goto(self._name.parent_context, tree_name)
return [Definition(self._evaluator, d) for d in defs]
@memoize_method
@@ -306,6 +313,7 @@ class BaseDefinition(object):
"""
Follow both statements and imports, as far as possible.
"""
return self._name.infer()
if self._name.api_type == 'expr_stmt':
return self._evaluator.eval_statement(self._definition)
elif self._name.api_type == 'import':
@@ -351,9 +359,7 @@ class BaseDefinition(object):
return [_Param(self._evaluator, n) for n in get_param_names(context)]
def parent(self):
scope = self._definition.get_parent_scope()
scope = self._evaluator.wrap(scope)
return Definition(self._evaluator, scope.name)
return Definition(self._evaluator, self._name.parent_context.name)
def __repr__(self):
return "<%s %s>" % (type(self).__name__, self.description)
@@ -371,7 +377,7 @@ class BaseDefinition(object):
if self.in_builtin_module():
return ''
path = self._definition.get_parent_until().path
path = self._name.get_root_context().py__file__()
parser = load_parser(path)
lines = common.splitlines(parser.source)
@@ -401,7 +407,7 @@ class Completion(BaseDefinition):
and self.type == 'Function':
append = '('
if isinstance(self._definition, tree.Param) and self._stack is not None:
if isinstance(self._name, ParamName) and self._stack is not None:
node_names = list(self._stack.get_node_names(self._evaluator.grammar))
if 'trailer' in node_names and 'argument' not in node_names:
append += '='
@@ -438,9 +444,10 @@ class Completion(BaseDefinition):
@property
def description(self):
"""Provide a description of the completion object."""
if self._definition is None:
return self._name.string_name
# TODO improve the class structure.
return Definition.description.__get__(self)
# TODO remove
t = self.type
if t == 'statement' or t == 'import':
desc = self._definition.get_code()
@@ -461,20 +468,20 @@ class Completion(BaseDefinition):
the ``foo.docstring(fast=False)`` on every object, because it
parses all libraries starting with ``a``.
"""
definition = self._definition
if isinstance(definition, tree.Import):
raise DeprecationWarning
i = imports.ImportWrapper(self._evaluator, self._name)
if len(i.import_path) > 1 or not fast:
followed = self._follow_statements_imports()
context = self._name.parent_context
if isinstance(self._name, imports.ImportName):
if fast:
return ''
else:
followed = self._name.infer()
if followed:
# TODO: Use all of the followed objects as input to Documentation.
definition = list(followed)[0]
context = next(iter(followed))
if raw:
return _Help(definition).raw()
return _Help(context).raw()
else:
return _Help(definition).full()
return _Help(context).full()
@property
def type(self):
@@ -772,7 +779,7 @@ class _Help(object):
def full(self):
try:
return self._name.doc
return self._name.get_node().doc
except AttributeError:
return self.raw()
@@ -782,7 +789,7 @@ class _Help(object):
See :attr:`doc` for example.
"""
try:
return self._name.raw_doc
except AttributeError:
node = self._name.get_node()
if node is None:
return ''
return node.raw_doc

View File

@@ -112,6 +112,17 @@ class CompiledObject(Context):
params.append(Param(parts, self))
return params
def get_param_names(self):
params_str, ret = self._parse_function_doc()
tokens = params_str.split(',')
if inspect.ismethoddescriptor(self.obj):
tokens.insert(0, 'self')
for p in tokens:
parts = p.strip().split('=')
if len(parts) > 1:
parts.insert(1, Operator('=', (0, 0)))
yield UnresolvableParamName(self, p[0])
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, repr(self.obj))
@@ -278,6 +289,17 @@ class CompiledName(AbstractNameDefinition):
return [_create_from_name(self._evaluator, module, self.parent_context, self.string_name)]
class UnresolvableParamName(AbstractNameDefinition):
api_type = 'param'
def __init__(self, compiled_obj, name):
self.parent_context = compiled_obj.parent_context
self.string_name = name
def infer(self):
return set()
class CompiledContextName(AbstractNameDefinition):
def __init__(self, parent_context, name):
self.string_name = name

View File

@@ -431,7 +431,7 @@ class Importer(object):
if self.str_import_path == ('flask', 'ext'):
# List Flask extensions like ``flask_foo``
for mod in self._get_module_names():
modname = str(mod)
modname = mod.string_name
if modname.startswith('flask_'):
extname = modname[len('flask_'):]
names.append(self._generate_name(extname))

View File

@@ -564,10 +564,14 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext)):
# modules on sys_path or whatever the search_path is.
paths = set()
for s in search_path:
other = os.path.join(s, unicode(self.name))
other = os.path.join(s, self.name.string_name)
if os.path.isdir(other):
paths.add(other)
return list(paths)
if paths:
return list(paths)
# TODO I'm not sure if this is how nested namespace
# packages work. The tests are not really good enough to
# show that.
# Default to this.
return [self._get_init_directory()]

View File

@@ -22,8 +22,8 @@ def test_preload_modules():
api.preload_module('sys')
check_loaded() # compiled (c_builtin) modules shouldn't be in the cache.
api.preload_module('json', 'token')
check_loaded('json', 'token')
api.preload_module('types', 'token')
check_loaded('types', 'token')
utils.parser_cache = temp_cache

View File

@@ -2,8 +2,8 @@ from textwrap import dedent
from jedi._compatibility import builtins, is_py3
from jedi.parser import load_grammar
from jedi.parser.tree import Function
from jedi.evaluate import compiled, representation
from jedi.evaluate import compiled, instance
from jedi.evaluate.representation import FunctionContext
from jedi.evaluate import Evaluator
from jedi import Script
@@ -16,25 +16,24 @@ def test_simple():
e = _evaluator()
bltn = compiled.CompiledObject(e, builtins)
obj = compiled.CompiledObject(e, '_str_', bltn)
upper = e.find_types(obj, 'upper')
assert len(upper) == 1
objs = list(e.execute(list(upper)[0]))
upper, = obj.py__getattribute__('upper')
objs = list(upper.execute_evaluated())
assert len(objs) == 1
assert isinstance(objs[0], representation.Instance)
assert isinstance(objs[0], instance.CompiledInstance)
def test_fake_loading():
e = _evaluator()
assert isinstance(compiled.create(e, next), Function)
assert isinstance(compiled.create(e, next), FunctionContext)
builtin = compiled.get_special_object(e, 'BUILTINS')
string = builtin.get_subscope_by_name('str')
string, = builtin.py__getattribute__('str')
from_name = compiled._create_from_name(e, builtin, string, '__init__')
assert isinstance(from_name, Function)
assert isinstance(from_name, FunctionContext)
def test_fake_docstr():
assert compiled.create(_evaluator(), next).raw_doc == next.__doc__
assert compiled.create(_evaluator(), next).get_node().raw_doc == next.__doc__
def test_parse_function_doc_illegal_docstr():

View File

@@ -10,7 +10,7 @@ def test_call_of_leaf_in_brackets():
type(x)
""")
last_x = names(s, references=True, definitions=False)[-1]
name = last_x._name
name = last_x._name.tree_name
call = helpers.call_of_leaf(name)
assert call == name

View File

@@ -97,7 +97,7 @@ def test_not_importable_file():
def test_import_unique():
src = "import os; os.path"
defs = jedi.Script(src, path='example.py').goto_definitions()
defs = [d._definition for d in defs]
defs = [d._name.parent_context for d in defs]
assert len(defs) == len(set(defs))

View File

@@ -49,16 +49,16 @@ def test_namespace_package():
for c in script_with_path(source + '; x.').completions():
if c.name == 'foo':
completion = c
solution = "statement: foo = '%s'" % solution
solution = "foo = '%s'" % solution
assert completion.description == solution
def test_nested_namespace_package():
CODE = 'from nested_namespaces.namespace.pkg import CONST'
code = 'from nested_namespaces.namespace.pkg import CONST'
sys_path = [dirname(__file__)]
script = jedi.Script(sys_path=sys_path, source=CODE, line=1, column=45)
script = jedi.Script(sys_path=sys_path, source=code, line=1, column=45)
result = script.goto_definitions()