mirror of
https://github.com/davidhalter/jedi.git
synced 2026-05-19 14:59:41 +08:00
Implement Import.is_nested method.
This commit is contained in:
@@ -610,11 +610,11 @@ class Script(object):
|
|||||||
|
|
||||||
def _analysis(self):
|
def _analysis(self):
|
||||||
#statements = set(chain(*self._parser.module().used_names.values()))
|
#statements = set(chain(*self._parser.module().used_names.values()))
|
||||||
stmts, imps = analysis.get_module_statements(self._parser.module())
|
stmts, imp_names = analysis.get_module_statements(self._parser.module())
|
||||||
# Sort the statements so that the results are reproducible.
|
# Sort the statements so that the results are reproducible.
|
||||||
for i in imps:
|
for n in imp_names:
|
||||||
iw = imports.ImportWrapper(self._evaluator, i,
|
iw = imports.ImportWrapper(self._evaluator, n).follow()
|
||||||
nested_resolve=True).follow()
|
i = n.get_definition()
|
||||||
if i.is_nested() and any(not isinstance(i, pr.Module) for i in iw):
|
if i.is_nested() and any(not isinstance(i, pr.Module) for i in iw):
|
||||||
analysis.add(self._evaluator, 'import-error', i.namespace_names[-1])
|
analysis.add(self._evaluator, 'import-error', i.namespace_names[-1])
|
||||||
for stmt in sorted(stmts, key=lambda obj: obj.start_pos):
|
for stmt in sorted(stmts, key=lambda obj: obj.start_pos):
|
||||||
|
|||||||
@@ -212,9 +212,10 @@ def get_module_statements(module):
|
|||||||
return new
|
return new
|
||||||
|
|
||||||
stmts = set()
|
stmts = set()
|
||||||
imports = set()
|
import_names = set()
|
||||||
for scope in module.walk():
|
for scope in module.walk():
|
||||||
imports |= set(scope.imports)
|
for imp in set(scope.imports):
|
||||||
|
import_names |= set(imp.get_defined_names())
|
||||||
stmts |= add_stmts(scope.statements)
|
stmts |= add_stmts(scope.statements)
|
||||||
stmts |= add_stmts(r for r in scope.returns if r is not None)
|
stmts |= add_stmts(r for r in scope.returns if r is not None)
|
||||||
|
|
||||||
@@ -224,4 +225,4 @@ def get_module_statements(module):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
stmts |= add_stmts(decorators)
|
stmts |= add_stmts(decorators)
|
||||||
return stmts, imports
|
return stmts, import_names
|
||||||
|
|||||||
+16
-11
@@ -32,9 +32,9 @@ from jedi.evaluate.cache import memoize_default, NO_DEFAULT
|
|||||||
|
|
||||||
|
|
||||||
class ModuleNotFound(Exception):
|
class ModuleNotFound(Exception):
|
||||||
def __init__(self, name_part):
|
def __init__(self, name):
|
||||||
super(ModuleNotFound, self).__init__()
|
super(ModuleNotFound, self).__init__()
|
||||||
self.name_part = name_part
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
def completion_names(evaluator, imp, pos):
|
def completion_names(evaluator, imp, pos):
|
||||||
@@ -101,16 +101,16 @@ class ImportWrapper(pr.Base):
|
|||||||
try:
|
try:
|
||||||
module, rest = importer.follow_file_system()
|
module, rest = importer.follow_file_system()
|
||||||
except ModuleNotFound as e:
|
except ModuleNotFound as e:
|
||||||
analysis.add(self._evaluator, 'import-error', e.name_part)
|
analysis.add(self._evaluator, 'import-error', e.name)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if module is None:
|
if module is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if self._import.is_nested() and not self.nested_resolve:
|
#if self._import.is_nested() and not self.nested_resolve:
|
||||||
scopes = [NestedImportModule(module, self._import)]
|
# scopes = [NestedImportModule(module, self._import)]
|
||||||
else:
|
#else:
|
||||||
scopes = [module]
|
scopes = [module]
|
||||||
|
|
||||||
#star_imports = remove_star_imports(self._evaluator, module)
|
#star_imports = remove_star_imports(self._evaluator, module)
|
||||||
#if star_imports:
|
#if star_imports:
|
||||||
@@ -127,7 +127,11 @@ class ImportWrapper(pr.Base):
|
|||||||
self._evaluator.find_types(s, rest[0], is_goto=True)
|
self._evaluator.find_types(s, rest[0], is_goto=True)
|
||||||
for s in scopes))
|
for s in scopes))
|
||||||
else:
|
else:
|
||||||
scopes = importer.follow_rest(scopes[0], rest)
|
print(self._import, scopes, rest)
|
||||||
|
if self._import.type == 'import_from':
|
||||||
|
scopes = importer.follow_rest(scopes[0], rest)
|
||||||
|
else:
|
||||||
|
scopes = []
|
||||||
debug.dbg('after import: %s', scopes)
|
debug.dbg('after import: %s', scopes)
|
||||||
if not scopes:
|
if not scopes:
|
||||||
analysis.add(self._evaluator, 'import-error', importer.import_path[-1])
|
analysis.add(self._evaluator, 'import-error', importer.import_path[-1])
|
||||||
@@ -135,6 +139,7 @@ class ImportWrapper(pr.Base):
|
|||||||
self._evaluator.recursion_detector.pop_stmt()
|
self._evaluator.recursion_detector.pop_stmt()
|
||||||
return scopes
|
return scopes
|
||||||
|
|
||||||
|
|
||||||
class ImportWrapper2(pr.Base):
|
class ImportWrapper2(pr.Base):
|
||||||
"""
|
"""
|
||||||
An ImportWrapper is the path of a `pr.Import` object.
|
An ImportWrapper is the path of a `pr.Import` object.
|
||||||
@@ -284,7 +289,7 @@ class ImportWrapper2(pr.Base):
|
|||||||
try:
|
try:
|
||||||
module, rest = self._importer.follow_file_system()
|
module, rest = self._importer.follow_file_system()
|
||||||
except ModuleNotFound as e:
|
except ModuleNotFound as e:
|
||||||
analysis.add(self._evaluator, 'import-error', e.name_part)
|
analysis.add(self._evaluator, 'import-error', e.name)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if module is None:
|
if module is None:
|
||||||
@@ -346,7 +351,7 @@ class NestedImportModule(pr.Module):
|
|||||||
# This is not an existing Import statement. Therefore, set position to
|
# This is not an existing Import statement. Therefore, set position to
|
||||||
# 0 (0 is not a valid line number).
|
# 0 (0 is not a valid line number).
|
||||||
zero = (0, 0)
|
zero = (0, 0)
|
||||||
names = [unicode(name_part) for name_part in i.namespace_names[1:]]
|
names = [unicode(name) for name in i.namespace_names[1:]]
|
||||||
name = helpers.FakeName(names, self._nested_import)
|
name = helpers.FakeName(names, self._nested_import)
|
||||||
new = pr.Import(i._sub_module, zero, zero, name)
|
new = pr.Import(i._sub_module, zero, zero, name)
|
||||||
new.parent = self._module
|
new.parent = self._module
|
||||||
@@ -435,7 +440,7 @@ class _Importer(object):
|
|||||||
@property
|
@property
|
||||||
def str_import_path(self):
|
def str_import_path(self):
|
||||||
"""Returns the import path as pure strings instead of `Name`."""
|
"""Returns the import path as pure strings instead of `Name`."""
|
||||||
return tuple(str(name_part) for name_part in self.import_path)
|
return tuple(str(name) for name in self.import_path)
|
||||||
|
|
||||||
def get_relative_path(self):
|
def get_relative_path(self):
|
||||||
path = self.file_path
|
path = self.file_path
|
||||||
|
|||||||
+11
-10
@@ -992,16 +992,7 @@ class Import(Simple):
|
|||||||
raise ValueError('Name should be defined in the import itself')
|
raise ValueError('Name should be defined in the import itself')
|
||||||
|
|
||||||
def is_nested(self):
|
def is_nested(self):
|
||||||
"""
|
return False # By default, sub classes may overwrite this behavior
|
||||||
This checks for the special case of nested imports, without aliases and
|
|
||||||
from statement::
|
|
||||||
|
|
||||||
import foo.bar
|
|
||||||
"""
|
|
||||||
return False
|
|
||||||
# TODO use this check differently?
|
|
||||||
return not self.alias and not self.from_names \
|
|
||||||
and len(self.namespace_names) > 1
|
|
||||||
|
|
||||||
def is_star_import(self):
|
def is_star_import(self):
|
||||||
return self.children[-1] == '*'
|
return self.children[-1] == '*'
|
||||||
@@ -1102,6 +1093,16 @@ class ImportName(Import):
|
|||||||
# dotted_names
|
# dotted_names
|
||||||
yield as_name.children[::2], alias
|
yield as_name.children[::2], alias
|
||||||
|
|
||||||
|
def is_nested(self):
|
||||||
|
"""
|
||||||
|
This checks for the special case of nested imports, without aliases and
|
||||||
|
from statement::
|
||||||
|
|
||||||
|
import foo.bar
|
||||||
|
"""
|
||||||
|
return [1 for path, alias in self._dotted_as_names()
|
||||||
|
if alias is None and len(path) > 1]
|
||||||
|
|
||||||
def aliases(self):
|
def aliases(self):
|
||||||
return dict((alias, path[-1]) for path, alias in self._dotted_as_names()
|
return dict((alias, path[-1]) for path, alias in self._dotted_as_names()
|
||||||
if alias is not None)
|
if alias is not None)
|
||||||
|
|||||||
Reference in New Issue
Block a user