From f4aad8bbfe7b58a9360e04547bdbd23fe9a76001 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 3 Jul 2018 00:58:24 +0200 Subject: [PATCH] Finally make it possible to use auto_import_modules for packages This means that you can now write 'from gi.repository import Gtk' and Gtk completions work. It also means that other libraries could be used like that for speed or other reasons. Fixes #531 --- jedi/evaluate/compiled/access.py | 5 ++++- jedi/evaluate/compiled/context.py | 4 ++++ jedi/evaluate/imports.py | 14 +++++++++++--- jedi/settings.py | 3 ++- test/test_settings.py | 13 ++++++++++++- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/jedi/evaluate/compiled/access.py b/jedi/evaluate/compiled/access.py index 97a8dd0b..b9bf5c0c 100644 --- a/jedi/evaluate/compiled/access.py +++ b/jedi/evaluate/compiled/access.py @@ -150,7 +150,7 @@ def load_module(evaluator, path=None, name=None, sys_path=None): __import__(dotted_path) except ImportError: # If a module is "corrupt" or not really a Python module or whatever. - debug.warning('Module %s not importable in path %s.', dotted_path, path) + print_to_stderr('Module %s not importable in path %s.' % (dotted_path, path)) return None except Exception: # Since __import__ pretty much makes code execution possible, just @@ -262,6 +262,9 @@ class DirectObjectAccess(object): def py__bases__(self): return [self._create_access_path(base) for base in self._obj.__bases__] + def py__path__(self): + return self._obj.__path__ + @_force_unicode_decorator def get_repr(self): builtins = 'builtins', '__builtin__' diff --git a/jedi/evaluate/compiled/context.py b/jedi/evaluate/compiled/context.py index a51717f0..2b87e3b1 100644 --- a/jedi/evaluate/compiled/context.py +++ b/jedi/evaluate/compiled/context.py @@ -81,6 +81,10 @@ class CompiledObject(Context): for access in self.access_handle.py__bases__() ) + @CheckAttribute + def py__path__(self): + return self.access_handle.py__path__() + def py__bool__(self): return self.access_handle.py__bool__() diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index 872ad1e1..5c72a0cd 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -277,6 +277,7 @@ class Importer(object): def follow(self): if not self.import_path: return NO_CONTEXTS + return self._do_import(self.import_path, self.sys_path_with_modifications()) def _do_import(self, import_path, sys_path): @@ -300,6 +301,14 @@ class Importer(object): # Old style return self._do_import(('flaskext',) + import_path[2:], sys_path) + if import_parts[0] in settings.auto_import_modules: + module = compiled.load_module( + self._evaluator, + name='.'.join(import_parts), + sys_path=sys_path, + ) + return ContextSet(module) + module_name = '.'.join(import_parts) try: return ContextSet(self._evaluator.module_cache.get(module_name)) @@ -464,7 +473,7 @@ class Importer(object): def _load_module(evaluator, path=None, code=None, sys_path=None, - module_name=None, safe_module_name=False): + module_name=None, safe_module_name=False, auto_import=False): try: return evaluator.module_cache.get(module_name) except KeyError: @@ -485,9 +494,8 @@ def _load_module(evaluator, path=None, code=None, sys_path=None, if sys_path is None: sys_path = evaluator.get_sys_path() - dotted_path = path and dotted_from_fs_path(path, sys_path) if path is not None and path.endswith(('.py', '.zip', '.egg')) \ - and dotted_path not in settings.auto_import_modules: + and not auto_import: module_node = evaluator.parse( code=code, path=path, cache=True, diff_cache=True, diff --git a/jedi/settings.py b/jedi/settings.py index f1ae6dbb..436fadfc 100644 --- a/jedi/settings.py +++ b/jedi/settings.py @@ -144,7 +144,8 @@ Check for `isinstance` and other information to infer a type. """ auto_import_modules = [ - 'hashlib', # setattr + 'hashlib', # hashlib is mostly using setattr, which jedi doesn't understand + 'gi', # This third-party repository (GTK stuff) doesn't really work with jedi ] """ Modules that are not analyzed but imported, although they contain Python code. diff --git a/test/test_settings.py b/test/test_settings.py index bbe644e6..4958ca45 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -1,8 +1,19 @@ +import pytest + from jedi import settings from jedi.evaluate.compiled import CompiledContextName -def test_base_auto_import_modules(monkeypatch, Script): +@pytest.fixture() +def auto_import_json(monkeypatch): monkeypatch.setattr(settings, 'auto_import_modules', ['json']) + + +def test_base_auto_import_modules(auto_import_json, Script): loads, = Script('import json; json.loads').goto_definitions() assert isinstance(loads._name, CompiledContextName) + + +def test_auto_import_modules_imports(auto_import_json, Script): + main, = Script('from json import tool; tool.main').goto_definitions() + assert isinstance(main._name, CompiledContextName)