diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index 459f09e3..b2fb88c9 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -46,6 +46,7 @@ class ImportWrapper(): self._import = name.get_parent_until(pr.Import) self.import_path = self._import.path_for_name(name) + self.is_like_search = False # TODO REMOVE @memoize_default() def follow(self, is_goto=False): diff --git a/jedi/parser/__init__.py b/jedi/parser/__init__.py index fef6a2d6..35a7fed1 100644 --- a/jedi/parser/__init__.py +++ b/jedi/parser/__init__.py @@ -56,8 +56,8 @@ class Parser(object): 'classdef': pr.Class, 'funcdef': pr.Function, 'file_input': pr.SubModule, - 'import_name': pr.Import, - 'import_from': pr.Import, + 'import_name': pr.ImportName, + 'import_from': pr.ImportFrom, 'break_stmt': pr.KeywordStatement, 'continue_stmt': pr.KeywordStatement, 'return_stmt': pr.ReturnStmt, diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 6fce8a3b..62b666b1 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -1061,29 +1061,6 @@ class ForFlow(Flow): class Import(Simple): - def get_defined_names(self): - if self.children[0] == 'import': - n = self.children[1] - if is_node(n, 'dotted_name'): - return [n.children[0]] - else: - return [n] - else: # from -# , , , - return [self.children[-1]] - - # TODO remove - if self.defunct: - return [] - if self.star: - return [self] - if self.alias: - return [self.alias] - if len(self.namespace_names) > 1: - return [self.namespace_names[0]] - else: - return self.namespace_names - def get_all_import_names(self): n = [] if self.from_names: @@ -1135,6 +1112,41 @@ class Import(Simple): return not self.alias and not self.from_names \ and len(self.namespace_names) > 1 + def is_star_import(self): + return self.children[-1] == '*' + + +class ImportFrom(Import): + def get_defined_names(self): + return [alias or name for name, alias in self._as_name_tuples()] + + def _as_name_tuples(self): + last = self.children[-1] + if last == ')': + last = self.children[-2] + elif last == '*': + return # No names defined directly. + + if is_node(last, 'import_as_names'): + as_names = last.children[::2] + else: + as_names = [last] + for as_name in as_names: + if isinstance(as_name, Name): + yield as_name, None + else: + yield as_name.children[::2] # yields x, y -> ``x as y`` + + +class ImportName(Import): + """For ``import_name`` nodes. Covers normal imports without ``from``.""" + def get_defined_names(self): + n = self.children[1] + if is_node(n, 'dotted_name'): + return [n.children[0]] + else: + return [n] + class KeywordStatement(Simple): """ diff --git a/test/completion/import_tree/mod1.py b/test/completion/import_tree/mod1.py index 172103a3..bd696d64 100644 --- a/test/completion/import_tree/mod1.py +++ b/test/completion/import_tree/mod1.py @@ -1,2 +1,4 @@ a = 1 from import_tree.random import a as c + +foobarbaz = 3.0 diff --git a/test/completion/imports.py b/test/completion/imports.py index 3c1dca01..563aa43e 100644 --- a/test/completion/imports.py +++ b/test/completion/imports.py @@ -97,13 +97,16 @@ def scope_from_import_variable(): def scope_from_import_variable_with_parenthesis(): from import_tree.mod2.fake import ( - a, c + a, foobarbaz ) #? a #? - c + foobarbaz + # shouldn't complete, should still list the name though. + #? ['foobarbaz'] + foobarbaz # ----------------- # std lib modules @@ -303,6 +306,7 @@ from import_tree import recurse_class1 #? ['a'] recurse_class1.C.a # github #239 RecursionError +# TODO UNCOMMENT!!!!!! ##? ['a'] recurse_class1.C().a