diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index bc45b3c9..401b2423 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -100,9 +100,7 @@ class ImportWrapper(pr.Base): self._evaluator.find_types(s, rest[0], is_goto=True) for s in scopes)) else: - scopes = list(chain.from_iterable( - self._evaluator.find_types(s, rest[0]) - for s in scopes)) + scopes = importer.follow_rest(scopes[0], rest) debug.dbg('after import: %s', scopes) if not scopes: analysis.add(self._evaluator, 'import-error', importer.import_path[-1]) @@ -440,12 +438,26 @@ class _Importer(object): return [] if rest: # follow the rest of the import (not FS -> classes, functions) - return [] - raise NotImplementedError - # old - return evaluator.follow_path(iter(rest), [scope], scope) + return self.follow_rest(scope, rest) return [scope] + def follow_rest(self, module, rest): + # Either os.path or path length is smaller. + if len(rest) < 2 or len(self.str_import_path) < 4 \ + and ('os', 'path') == self.str_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 = [module] + for r in rest: + scopes = list(chain.from_iterable( + self._evaluator.find_types(s, r) + for s in scopes)) + return scopes + else: + return [] + @memoize_default(NO_DEFAULT) def follow_file_system(self): # Handle "magic" Flask extension imports: @@ -459,22 +471,7 @@ class _Importer(object): self.import_path = ('flaskext',) + orig_path[2:] return self._real_follow_file_system() - obj, rest = self._real_follow_file_system() - - # os.path handling - if len(self.str_import_path) < 4 \ - and ('os', 'path') == self.str_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 = [obj] - for r in rest: - scopes = list(chain.from_iterable( - self._evaluator.find_types(s, r) - for s in scopes)) - return scopes[0], [] - return obj, rest + return self._real_follow_file_system() def _real_follow_file_system(self): if self.file_path: @@ -645,8 +642,13 @@ class _Importer(object): if os.path.isdir(flaskext): names += self._get_module_names([flaskext]) - from jedi.evaluate import finder + from jedi.evaluate import finder, representation as er for scope in self.follow(evaluator): + # Non-modules are not completable. + if not isinstance(scope, er.ModuleWrapper) and not (isinstance(scope, + compiled.CompiledObject) and scope.type() == 'module'): + continue + # namespace packages if isinstance(scope, pr.Module) and scope.path.endswith('__init__.py'): pkg_path = os.path.dirname(scope.path)