mirror of
https://github.com/davidhalter/jedi.git
synced 2026-01-31 04:05:21 +08:00
Implement Import.is_nested method.
This commit is contained in:
@@ -610,11 +610,11 @@ class Script(object):
|
||||
|
||||
def _analysis(self):
|
||||
#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.
|
||||
for i in imps:
|
||||
iw = imports.ImportWrapper(self._evaluator, i,
|
||||
nested_resolve=True).follow()
|
||||
for n in imp_names:
|
||||
iw = imports.ImportWrapper(self._evaluator, n).follow()
|
||||
i = n.get_definition()
|
||||
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])
|
||||
for stmt in sorted(stmts, key=lambda obj: obj.start_pos):
|
||||
|
||||
@@ -212,9 +212,10 @@ def get_module_statements(module):
|
||||
return new
|
||||
|
||||
stmts = set()
|
||||
imports = set()
|
||||
import_names = set()
|
||||
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(r for r in scope.returns if r is not None)
|
||||
|
||||
@@ -224,4 +225,4 @@ def get_module_statements(module):
|
||||
pass
|
||||
else:
|
||||
stmts |= add_stmts(decorators)
|
||||
return stmts, imports
|
||||
return stmts, import_names
|
||||
|
||||
@@ -32,9 +32,9 @@ from jedi.evaluate.cache import memoize_default, NO_DEFAULT
|
||||
|
||||
|
||||
class ModuleNotFound(Exception):
|
||||
def __init__(self, name_part):
|
||||
def __init__(self, name):
|
||||
super(ModuleNotFound, self).__init__()
|
||||
self.name_part = name_part
|
||||
self.name = name
|
||||
|
||||
|
||||
def completion_names(evaluator, imp, pos):
|
||||
@@ -101,16 +101,16 @@ class ImportWrapper(pr.Base):
|
||||
try:
|
||||
module, rest = importer.follow_file_system()
|
||||
except ModuleNotFound as e:
|
||||
analysis.add(self._evaluator, 'import-error', e.name_part)
|
||||
analysis.add(self._evaluator, 'import-error', e.name)
|
||||
return []
|
||||
|
||||
if module is None:
|
||||
return []
|
||||
|
||||
if self._import.is_nested() and not self.nested_resolve:
|
||||
scopes = [NestedImportModule(module, self._import)]
|
||||
else:
|
||||
scopes = [module]
|
||||
#if self._import.is_nested() and not self.nested_resolve:
|
||||
# scopes = [NestedImportModule(module, self._import)]
|
||||
#else:
|
||||
scopes = [module]
|
||||
|
||||
#star_imports = remove_star_imports(self._evaluator, module)
|
||||
#if star_imports:
|
||||
@@ -127,7 +127,11 @@ class ImportWrapper(pr.Base):
|
||||
self._evaluator.find_types(s, rest[0], is_goto=True)
|
||||
for s in scopes))
|
||||
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)
|
||||
if not scopes:
|
||||
analysis.add(self._evaluator, 'import-error', importer.import_path[-1])
|
||||
@@ -135,6 +139,7 @@ class ImportWrapper(pr.Base):
|
||||
self._evaluator.recursion_detector.pop_stmt()
|
||||
return scopes
|
||||
|
||||
|
||||
class ImportWrapper2(pr.Base):
|
||||
"""
|
||||
An ImportWrapper is the path of a `pr.Import` object.
|
||||
@@ -284,7 +289,7 @@ class ImportWrapper2(pr.Base):
|
||||
try:
|
||||
module, rest = self._importer.follow_file_system()
|
||||
except ModuleNotFound as e:
|
||||
analysis.add(self._evaluator, 'import-error', e.name_part)
|
||||
analysis.add(self._evaluator, 'import-error', e.name)
|
||||
return []
|
||||
|
||||
if module is None:
|
||||
@@ -346,7 +351,7 @@ class NestedImportModule(pr.Module):
|
||||
# This is not an existing Import statement. Therefore, set position to
|
||||
# 0 (0 is not a valid line number).
|
||||
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)
|
||||
new = pr.Import(i._sub_module, zero, zero, name)
|
||||
new.parent = self._module
|
||||
@@ -435,7 +440,7 @@ class _Importer(object):
|
||||
@property
|
||||
def str_import_path(self):
|
||||
"""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):
|
||||
path = self.file_path
|
||||
|
||||
@@ -992,16 +992,7 @@ class Import(Simple):
|
||||
raise ValueError('Name should be defined in the import itself')
|
||||
|
||||
def is_nested(self):
|
||||
"""
|
||||
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
|
||||
return False # By default, sub classes may overwrite this behavior
|
||||
|
||||
def is_star_import(self):
|
||||
return self.children[-1] == '*'
|
||||
@@ -1102,6 +1093,16 @@ class ImportName(Import):
|
||||
# dotted_names
|
||||
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):
|
||||
return dict((alias, path[-1]) for path, alias in self._dotted_as_names()
|
||||
if alias is not None)
|
||||
|
||||
Reference in New Issue
Block a user