Directly load modules if possible, with this it's not necessary anymore to use dotted_from_fs_path, also fixes #1013.

This commit is contained in:
Dave Halter
2018-07-05 10:03:05 +02:00
parent a12d62e9c9
commit 508ed7e5b8
4 changed files with 10 additions and 53 deletions

View File

@@ -5,11 +5,9 @@ from textwrap import dedent
import operator as op
from collections import namedtuple
from jedi import debug
from jedi._compatibility import unicode, is_py3, is_py34, builtins, \
py_version, force_unicode, print_to_stderr
from jedi.evaluate.compiled.getattr_static import getattr_static
from jedi.evaluate.utils import dotted_from_fs_path
MethodDescriptorType = type(str.replace)
@@ -137,20 +135,13 @@ def create_access(evaluator, obj):
return evaluator.compiled_subprocess.get_or_create_access_handle(obj)
def load_module(evaluator, path=None, name=None, sys_path=None):
if sys_path is None:
sys_path = list(evaluator.get_sys_path())
if path is not None:
dotted_path = dotted_from_fs_path(path, sys_path=sys_path)
else:
dotted_path = name
def load_module(evaluator, dotted_name, sys_path):
temp, sys.path = sys.path, sys_path
try:
__import__(dotted_path)
__import__(dotted_name)
except ImportError:
# If a module is "corrupt" or not really a Python module or whatever.
print_to_stderr('Module %s not importable in path %s.' % (dotted_path, path))
print_to_stderr('Module %s not importable.' % dotted_name)
return None
except Exception:
# Since __import__ pretty much makes code execution possible, just
@@ -163,7 +154,7 @@ def load_module(evaluator, path=None, name=None, sys_path=None):
# Just access the cache after import, because of #59 as well as the very
# complicated import structure of Python.
module = sys.modules[dotted_path]
module = sys.modules[dotted_name]
return create_access_path(evaluator, module)

View File

@@ -26,7 +26,7 @@ from jedi.evaluate import sys_path
from jedi.evaluate import helpers
from jedi.evaluate import compiled
from jedi.evaluate import analysis
from jedi.evaluate.utils import unite, dotted_from_fs_path
from jedi.evaluate.utils import unite
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.filters import AbstractNameDefinition
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
@@ -304,7 +304,7 @@ class Importer(object):
if import_parts[0] in settings.auto_import_modules:
module = compiled.load_module(
self._evaluator,
name='.'.join(import_parts),
dotted_name='.'.join(import_parts),
sys_path=sys_path,
)
return ContextSet(module)
@@ -508,7 +508,7 @@ def _load_module(evaluator, path=None, code=None, sys_path=None,
code_lines=get_cached_code_lines(evaluator.grammar, path),
)
else:
module = compiled.load_module(evaluator, path=path, sys_path=sys_path)
module = compiled.load_module(evaluator, dotted_name=module_name, sys_path=sys_path)
if module is not None and module_name is not None:
add_module_to_cache(evaluator, module_name, module, safe=safe_module_name)
@@ -553,7 +553,8 @@ def get_modules_containing_name(evaluator, modules, name):
module_name = sys_path.dotted_path_in_sys_path(e_sys_path, path)
module = _load_module(
evaluator, path, code,
sys_path=e_sys_path, module_name=module_name
sys_path=e_sys_path,
module_name=module_name
)
return module

View File

@@ -117,38 +117,3 @@ def indent_block(text, indention=' '):
text = text[:-1]
lines = text.split('\n')
return '\n'.join(map(lambda s: indention + s, lines)) + temp
def dotted_from_fs_path(fs_path, sys_path):
"""
Changes `/usr/lib/python3.4/email/utils.py` to `email.utils`. I.e.
compares the path with sys.path and then returns the dotted_path. If the
path is not in the sys.path, just returns None.
"""
if os.path.basename(fs_path).startswith('__init__.'):
# We are calculating the path. __init__ files are not interesting.
fs_path = os.path.dirname(fs_path)
# prefer
# - UNIX
# /path/to/pythonX.Y/lib-dynload
# /path/to/pythonX.Y/site-packages
# - Windows
# C:\path\to\DLLs
# C:\path\to\Lib\site-packages
# over
# - UNIX
# /path/to/pythonX.Y
# - Windows
# C:\path\to\Lib
path = ''
for s in sys_path:
if (fs_path.startswith(s) and len(path) < len(s)):
path = s
# - Window
# X:\path\to\lib-dynload/datetime.pyd => datetime
module_path = fs_path[len(path):].lstrip(os.path.sep).lstrip('/')
# - Window
# Replace like X:\path\to\something/foo/bar.py
return _path_re.sub('', module_path).replace(os.path.sep, '.').replace('/', '.')

View File

@@ -44,7 +44,7 @@ def test_versions(version):
def test_load_module(evaluator):
access_path = evaluator.compiled_subprocess.load_module(
name=u'math',
dotted_name=u'math',
sys_path=evaluator.get_sys_path()
)
name, access_handle = access_path.accesses[0]