mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 14:34:31 +08:00
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:
@@ -5,11 +5,9 @@ from textwrap import dedent
|
|||||||
import operator as op
|
import operator as op
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from jedi import debug
|
|
||||||
from jedi._compatibility import unicode, is_py3, is_py34, builtins, \
|
from jedi._compatibility import unicode, is_py3, is_py34, builtins, \
|
||||||
py_version, force_unicode, print_to_stderr
|
py_version, force_unicode, print_to_stderr
|
||||||
from jedi.evaluate.compiled.getattr_static import getattr_static
|
from jedi.evaluate.compiled.getattr_static import getattr_static
|
||||||
from jedi.evaluate.utils import dotted_from_fs_path
|
|
||||||
|
|
||||||
|
|
||||||
MethodDescriptorType = type(str.replace)
|
MethodDescriptorType = type(str.replace)
|
||||||
@@ -137,20 +135,13 @@ def create_access(evaluator, obj):
|
|||||||
return evaluator.compiled_subprocess.get_or_create_access_handle(obj)
|
return evaluator.compiled_subprocess.get_or_create_access_handle(obj)
|
||||||
|
|
||||||
|
|
||||||
def load_module(evaluator, path=None, name=None, sys_path=None):
|
def load_module(evaluator, dotted_name, sys_path):
|
||||||
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
|
|
||||||
|
|
||||||
temp, sys.path = sys.path, sys_path
|
temp, sys.path = sys.path, sys_path
|
||||||
try:
|
try:
|
||||||
__import__(dotted_path)
|
__import__(dotted_name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# If a module is "corrupt" or not really a Python module or whatever.
|
# 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
|
return None
|
||||||
except Exception:
|
except Exception:
|
||||||
# Since __import__ pretty much makes code execution possible, just
|
# 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
|
# Just access the cache after import, because of #59 as well as the very
|
||||||
# complicated import structure of Python.
|
# complicated import structure of Python.
|
||||||
module = sys.modules[dotted_path]
|
module = sys.modules[dotted_name]
|
||||||
return create_access_path(evaluator, module)
|
return create_access_path(evaluator, module)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from jedi.evaluate import sys_path
|
|||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate import analysis
|
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.cache import evaluator_method_cache
|
||||||
from jedi.evaluate.filters import AbstractNameDefinition
|
from jedi.evaluate.filters import AbstractNameDefinition
|
||||||
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
|
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:
|
if import_parts[0] in settings.auto_import_modules:
|
||||||
module = compiled.load_module(
|
module = compiled.load_module(
|
||||||
self._evaluator,
|
self._evaluator,
|
||||||
name='.'.join(import_parts),
|
dotted_name='.'.join(import_parts),
|
||||||
sys_path=sys_path,
|
sys_path=sys_path,
|
||||||
)
|
)
|
||||||
return ContextSet(module)
|
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),
|
code_lines=get_cached_code_lines(evaluator.grammar, path),
|
||||||
)
|
)
|
||||||
else:
|
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:
|
if module is not None and module_name is not None:
|
||||||
add_module_to_cache(evaluator, module_name, module, safe=safe_module_name)
|
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_name = sys_path.dotted_path_in_sys_path(e_sys_path, path)
|
||||||
module = _load_module(
|
module = _load_module(
|
||||||
evaluator, path, code,
|
evaluator, path, code,
|
||||||
sys_path=e_sys_path, module_name=module_name
|
sys_path=e_sys_path,
|
||||||
|
module_name=module_name
|
||||||
)
|
)
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
|||||||
@@ -117,38 +117,3 @@ def indent_block(text, indention=' '):
|
|||||||
text = text[:-1]
|
text = text[:-1]
|
||||||
lines = text.split('\n')
|
lines = text.split('\n')
|
||||||
return '\n'.join(map(lambda s: indention + s, lines)) + temp
|
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('/', '.')
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ def test_versions(version):
|
|||||||
|
|
||||||
def test_load_module(evaluator):
|
def test_load_module(evaluator):
|
||||||
access_path = evaluator.compiled_subprocess.load_module(
|
access_path = evaluator.compiled_subprocess.load_module(
|
||||||
name=u'math',
|
dotted_name=u'math',
|
||||||
sys_path=evaluator.get_sys_path()
|
sys_path=evaluator.get_sys_path()
|
||||||
)
|
)
|
||||||
name, access_handle = access_path.accesses[0]
|
name, access_handle = access_path.accesses[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user