1
0
forked from VimPlug/jedi

again a temporary follow_definition for imports

This commit is contained in:
Dave Halter
2014-03-21 09:27:52 +01:00
parent 1703f7cca6
commit a06310db4a
2 changed files with 31 additions and 53 deletions

View File

@@ -400,8 +400,14 @@ class Completion(BaseDefinition):
if self._definition.isinstance(pr.Statement): if self._definition.isinstance(pr.Statement):
defs = self._evaluator.eval_statement(self._definition) defs = self._evaluator.eval_statement(self._definition)
elif self._definition.isinstance(pr.Import): elif self._definition.isinstance(pr.Import):
print(self._definition) print('ha', self._definition, repr(self._name))
defs = imports.strip_imports(self._evaluator, [self._definition]) i = imports.ImportPath(self._evaluator, self._definition, True)
print('h', i.import_path + [unicode(self._name)])
defs = imports.Importer(i.import_path + [unicode(self._name)],
i._importer.module).follow_file_system()[0]
defs = [defs]
print(defs)
#defs = imports.strip_imports(self._evaluator, [self._definition])
else: else:
return [self] return [self]

View File

@@ -64,15 +64,19 @@ class ImportPath(pr.Base):
import_path = [str(name_part) for name_part in import_path] import_path = [str(name_part) for name_part in import_path]
for i in range(kill_count + int(is_like_search)): for i in range(kill_count + int(is_like_search)):
import_path.pop() if import_path:
import_path.pop()
module = import_stmt.get_parent_until() module = import_stmt.get_parent_until()
self._importer = Importer(evaluator, import_path, module, self._importer = Importer(import_path, module, import_stmt.relative_count)
import_stmt.relative_count)
def __repr__(self): def __repr__(self):
return '<%s: %s>' % (type(self).__name__, self.import_stmt) return '<%s: %s>' % (type(self).__name__, self.import_stmt)
@property
def import_path(self):
return self._importer.import_path
def get_defined_names(self, on_import_stmt=False): def get_defined_names(self, on_import_stmt=False):
names = [] names = []
for scope in self.follow(): for scope in self.follow():
@@ -95,12 +99,12 @@ class ImportPath(pr.Base):
if on_import_stmt and isinstance(scope, pr.Module) \ if on_import_stmt and isinstance(scope, pr.Module) \
and scope.path.endswith('__init__.py'): and scope.path.endswith('__init__.py'):
pkg_path = os.path.dirname(scope.path) pkg_path = os.path.dirname(scope.path)
paths = self._importer.namespace_packages(pkg_path, self._importer.import_path) paths = self._importer.namespace_packages(pkg_path, self.import_path)
names += self._get_module_names([pkg_path] + paths) names += self._get_module_names([pkg_path] + paths)
if self.is_just_from: if self.is_just_from:
# In the case of an import like `from x.` we don't need to # In the case of an import like `from x.` we don't need to
# add all the variables. # add all the variables.
if ['os'] == self._importer.import_path and not self._is_relative_import(): if ['os'] == self.import_path and not self._is_relative_import():
# os.path is a hardcoded exception, because it's a # os.path is a hardcoded exception, because it's a
# ``sys.modules`` modification. # ``sys.modules`` modification.
names.append(self._generate_name('path')) names.append(self._generate_name('path'))
@@ -122,10 +126,11 @@ class ImportPath(pr.Base):
def _generate_name(self, name): def _generate_name(self, name):
parent = self.import_stmt parent = self.import_stmt
inf_pos = float('inf'), float('inf')
# Generate a statement that reflects autocompletion names. # Generate a statement that reflects autocompletion names.
#if is_like_search: #if self.is_like_search:
# parent = pr.Import(self.GlobalNamespace, inf_pos, inf_pos, n
#parent = Importer(self.import_path + [name], self._importer.module)
inf_pos = float('inf'), float('inf')
return pr.Name(self.GlobalNamespace, [(name, inf_pos)], return pr.Name(self.GlobalNamespace, [(name, inf_pos)],
inf_pos, inf_pos, parent) inf_pos, inf_pos, parent)
@@ -181,9 +186,9 @@ class ImportPath(pr.Base):
if self._evaluator.recursion_detector.push_stmt(self.import_stmt): if self._evaluator.recursion_detector.push_stmt(self.import_stmt):
# check recursion # check recursion
return [] return []
if self._importer.import_path: if self.import_path:
try: try:
scope, rest = self._importer._follow_file_system() scope, rest = self._importer.follow_file_system()
except ModuleNotFound: except ModuleNotFound:
debug.warning('Module not found: %s', self.import_stmt) debug.warning('Module not found: %s', self.import_stmt)
return [] return []
@@ -194,7 +199,7 @@ class ImportPath(pr.Base):
# follow the rest of the import (not FS -> classes, functions) # follow the rest of the import (not FS -> classes, functions)
if len(rest) > 1 or rest and self.is_like_search: if len(rest) > 1 or rest and self.is_like_search:
scopes = [] scopes = []
if ['os', 'path'] == self._importer.import_path[:2] \ if ['os', 'path'] == self.import_path[:2] \
and not self._is_relative_import(): and not self._is_relative_import():
# This is a huge exception, we follow a nested import # This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python # ``os.path``, because it's a very important one in Python
@@ -221,9 +226,10 @@ class ImportPath(pr.Base):
class Importer(object): class Importer(object):
def __init__(self, evaluator, import_path, module, level=0): def __init__(self, import_path, module, level=0):
""" """
An implementation similar to ``__import__``. An implementation similar to ``__import__``. Use `follow_file_system`
to actually follow the imports.
*level* specifies whether to use absolute or relative imports. 0 (the *level* specifies whether to use absolute or relative imports. 0 (the
default) means only perform absolute imports. Positive values for level default) means only perform absolute imports. Positive values for level
@@ -233,10 +239,9 @@ class Importer(object):
:param import_path: List of namespaces (strings). :param import_path: List of namespaces (strings).
""" """
self._evaluator = evaluator
self.import_path = import_path self.import_path = import_path
self.level = level self.level = level
self._module = module self.module = module
path = module.path path = module.path
# TODO abspath # TODO abspath
self.file_path = os.path.dirname(path) if path is not None else None self.file_path = os.path.dirname(path) if path is not None else None
@@ -259,45 +264,12 @@ class Importer(object):
new = os.path.sep.join(parts[:i]) new = os.path.sep.join(parts[:i])
in_path.append(new) in_path.append(new)
return in_path + sys_path.sys_path_with_modifications(self._module) return in_path + sys_path.sys_path_with_modifications(self.module)
def follow(self, is_goto=False): def follow_file_system(self):
"""
Returns the imported modules.
"""
try:
scope, rest = self._follow_file_system()
except ModuleNotFound:
debug.warning('Module not found: %s', self.import_path)
return [], None
scopes = [scope]
scopes += remove_star_imports(self._evaluator, scope)
# follow the rest of the import (not FS -> classes, functions)
if len(rest) > 1 or rest and self.is_like_search:
scopes = []
if ['os', 'path'] == self.import_path[:2] and self.level == 0:
# This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python
# that is being achieved by messing with ``sys.modules`` in
# ``os``.
scopes = self._evaluator.follow_path(iter(rest), [scope], scope)
elif rest:
if is_goto:
scopes = itertools.chain.from_iterable(
self._evaluator.find_types(s, rest[0], is_goto=True)
for s in scopes)
else:
scopes = itertools.chain.from_iterable(
self._evaluator.follow_path(iter(rest), [s], s)
for s in scopes)
return list(scopes)
def _follow_file_system(self):
if self.file_path: if self.file_path:
sys_path_mod = list(self.sys_path_with_modifications()) sys_path_mod = list(self.sys_path_with_modifications())
if not self._module.has_explicit_absolute_import: if not self.module.has_explicit_absolute_import:
# If the module explicitly asks for absolute imports, # If the module explicitly asks for absolute imports,
# there's probably a bogus local one. # there's probably a bogus local one.
sys_path_mod.insert(0, self.file_path) sys_path_mod.insert(0, self.file_path)