diff --git a/jedi/_compatibility.py b/jedi/_compatibility.py index 64469c8a..e5200bfc 100644 --- a/jedi/_compatibility.py +++ b/jedi/_compatibility.py @@ -35,7 +35,7 @@ class DummyFile(object): del self.loader -def find_module_py34(string, path=None, fullname=None): +def find_module_py34(string, path=None, full_name=None): implicit_namespace_pkg = False spec = None loader = None @@ -47,8 +47,8 @@ def find_module_py34(string, path=None, fullname=None): # We try to disambiguate implicit namespace pkgs with non implicit namespace pkgs if implicit_namespace_pkg: - fullname = string if not path else fullname - implicit_ns_info = ImplicitNSInfo(fullname, spec.submodule_search_locations._path) + full_name = string if not path else full_name + implicit_ns_info = ImplicitNSInfo(full_name, spec.submodule_search_locations._path) return None, implicit_ns_info, False # we have found the tail end of the dotted path @@ -56,7 +56,8 @@ def find_module_py34(string, path=None, fullname=None): loader = spec.loader return find_module_py33(string, path, loader) -def find_module_py33(string, path=None, loader=None, fullname=None): + +def find_module_py33(string, path=None, loader=None, full_name=None): loader = loader or importlib.machinery.PathFinder.find_module(string, path) if loader is None and path is None: # Fallback to find builtins @@ -109,7 +110,7 @@ def find_module_py33(string, path=None, loader=None, fullname=None): return module_file, module_path, is_package -def find_module_pre_py33(string, path=None, fullname=None): +def find_module_pre_py33(string, path=None, full_name=None): try: module_file, module_path, description = imp.find_module(string, path) module_type = description[2] @@ -149,7 +150,7 @@ def find_module_pre_py33(string, path=None, fullname=None): find_module = find_module_py33 if is_py33 else find_module_pre_py33 -find_module = find_module_py34 if is_py34 else find_module +find_module = find_module_py34 if is_py34 else find_module find_module.__doc__ = """ Provides information about a module. diff --git a/jedi/evaluate/compiled/subprocess/functions.py b/jedi/evaluate/compiled/subprocess/functions.py index e4f926f0..39b4f832 100644 --- a/jedi/evaluate/compiled/subprocess/functions.py +++ b/jedi/evaluate/compiled/subprocess/functions.py @@ -1,5 +1,8 @@ import sys +import os +import imp from jedi.evaluate.compiled import access +from jedi._compatibility import find_module def get_sys_path(): @@ -12,8 +15,8 @@ def load_module(evaluator, **kwargs): def get_compiled_method_return(evaluator, id, attribute, *args, **kwargs): handle = evaluator.compiled_subprocess.get_access_handle(id) - #print >> sys.stderr, handle, attribute, args, kwargs - #print(id, attribute, args, kwargs, file=sys.stderr) + # print >> sys.stderr, handle, attribute, args, kwargs + # print(id, attribute, args, kwargs, file=sys.stderr) return getattr(handle.access, attribute)(*args, **kwargs) @@ -23,3 +26,41 @@ def get_special_object(evaluator, identifier): def create_simple_object(evaluator, obj): return access.create_access_path(evaluator, obj) + + +def get_module_info(evaluator, sys_path=None, full_name=None, **kwargs): + if sys_path is not None: + sys.path, temp = sys_path, sys.path + try: + module_file, module_path, is_pkg = find_module(full_name=full_name, **kwargs) + except ImportError: + return None, None, None + finally: + if sys_path is not None: + sys.path = temp + + code = None + if is_pkg: + # In this case, we don't have a file yet. Search for the + # __init__ file. + if module_path.endswith(('.zip', '.egg')): + code = module_file.loader.get_source(full_name) + else: + module_path = _get_init_path(module_path) + elif module_file: + code = module_file.read() + module_file.close() + + return code, module_path, is_pkg + + +def _get_init_path(directory_path): + """ + The __init__ file can be searched in a directory. If found return it, else + None. + """ + for suffix, _, _ in imp.get_suffixes(): + path = os.path.join(directory_path, '__init__' + suffix) + if os.path.exists(path): + return path + return None diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index 912a9ae6..d00fdcbc 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -11,7 +11,6 @@ correct implementation is delegated to _compatibility. This module also supports import autocompletion, which means to complete statements like ``from datetim`` (curser at the end would return ``datetime``). """ -import imp import os import pkgutil import sys @@ -21,7 +20,7 @@ from parso.tree import search_ancestor from parso.cache import parser_cache from parso import python_bytes_to_unicode -from jedi._compatibility import find_module, unicode, ImplicitNSInfo +from jedi._compatibility import unicode, ImplicitNSInfo from jedi import debug from jedi import settings from jedi.evaluate import sys_path @@ -139,18 +138,6 @@ def _add_error(context, name, message=None): debug.warning('ImportError without origin: ' + message) -def get_init_path(directory_path): - """ - The __init__ file can be searched in a directory. If found return it, else - None. - """ - for suffix, _, _ in imp.get_suffixes(): - path = os.path.join(directory_path, '__init__' + suffix) - if os.path.exists(path): - return path - return None - - class ImportName(AbstractNameDefinition): start_pos = (1, 0) _level = 0 @@ -308,31 +295,6 @@ class Importer(object): except KeyError: pass - def _find_module(sys_path=None, **kwargs): - if sys_path is not None: - sys.path, temp = sys_path, sys.path - try: - module_file, module_path, is_pkg = find_module(**kwargs) - except ImportError: - return None, None, None - finally: - if sys_path is not None: - sys.path = temp - - code = None - if is_pkg: - # In this case, we don't have a file yet. Search for the - # __init__ file. - if module_path.endswith(('.zip', '.egg')): - code = module_file.loader.get_source(module_name) - else: - module_path = get_init_path(module_path) - elif module_file: - code = module_file.read() - module_file.close() - - return code, module_path, is_pkg - if len(import_path) > 1: # This is a recursive way of importing that works great with # the module cache. @@ -365,10 +327,10 @@ class Importer(object): # not important to be correct. if not isinstance(path, list): path = [path] - code, module_path, is_pkg = _find_module( + code, module_path, is_pkg = self._evaluator.compiled_subprocess.get_module_info( string=import_parts[-1], path=path, - fullname=module_name + full_name=module_name ) if module_path is not None: break @@ -380,9 +342,9 @@ class Importer(object): debug.dbg('search_module %s in %s', import_parts[-1], self.file_path) # Override the sys.path. It works only good that way. # Injecting the path directly into `find_module` did not work. - code, module_path, is_pkg = _find_module( + code, module_path, is_pkg = self._evaluator.compiled_subprocess.get_module_info( string=import_parts[-1], - fullname=module_name, + full_name=module_name, sys_path=sys_path, ) if module_path is None: