1
0
forked from VimPlug/jedi

Fix os path resolving issues

This commit is contained in:
Dave Halter
2019-08-21 00:22:34 +02:00
parent 14fc5ed289
commit 85f8f2a764
8 changed files with 53 additions and 48 deletions

View File

@@ -111,11 +111,11 @@ class InferenceState(object):
self.reset_recursion_limitations()
self.allow_different_encoding = True
def import_module(self, import_names, parent_module_context=None,
def import_module(self, import_names, parent_module_value=None,
sys_path=None, prefer_stubs=True):
if sys_path is None:
sys_path = self.get_sys_path()
return imports.import_module(self, import_names, parent_module_context,
return imports.import_module(self, import_names, parent_module_value,
sys_path, prefer_stubs=prefer_stubs)
@staticmethod

View File

@@ -103,6 +103,10 @@ class ModuleContext(AbstractContext):
def py__package__(self):
return self._value.py__package__
@property
def is_package(self):
return self._value.is_package
def get_filters(self, until_position=None, origin_scope=None):
filters = self._value.get_filters(origin_scope)
# Skip the first filter and replace it.

View File

@@ -91,7 +91,7 @@ def _load_stub_module(module):
module.inference_state,
import_names=module.string_names,
python_value_set=ValueSet([module]),
parent_module_context=None,
parent_module_value=None,
sys_path=module.inference_state.get_sys_path(),
)

View File

@@ -7,7 +7,7 @@ from jedi._compatibility import FileNotFoundError, cast_path
from jedi.parser_utils import get_cached_code_lines
from jedi.inference.base_value import ValueSet, NO_VALUES
from jedi.inference.gradual.stub_value import TypingModuleWrapper, StubModuleValue
from jedi.inference.context import ModuleContext
from jedi.inference.value import ModuleValue
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
@@ -90,27 +90,30 @@ def _cache_stub_file_map(version_info):
def import_module_decorator(func):
@wraps(func)
def wrapper(inference_state, import_names, parent_module_context, sys_path, prefer_stubs):
def wrapper(inference_state, import_names, parent_module_value, sys_path, prefer_stubs):
try:
python_value_set = inference_state.module_cache.get(import_names)
except KeyError:
if parent_module_context is not None and parent_module_context.is_stub():
parent_module_contexts = parent_module_context.non_stub_value_set
if parent_module_value is not None and parent_module_value.is_stub():
parent_module_values = parent_module_value.non_stub_value_set
else:
parent_module_contexts = [parent_module_context]
parent_module_values = [parent_module_value]
if import_names == ('os', 'path'):
# 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``.
python_parent = next(iter(parent_module_contexts))
python_parent = next(iter(parent_module_values))
if python_parent is None:
python_parent, = inference_state.import_module(('os',), prefer_stubs=False)
python_value_set = python_parent.py__getattribute__('path')
python_value_set = ValueSet.from_sets(
func(inference_state, (n,), None, sys_path,)
for n in ['posixpath', 'ntpath', 'macpath', 'os2emxpath']
)
else:
python_value_set = ValueSet.from_sets(
func(inference_state, import_names, p, sys_path,)
for p in parent_module_contexts
for p in parent_module_values
)
inference_state.module_cache.add(import_names, python_value_set)
@@ -118,7 +121,7 @@ def import_module_decorator(func):
return python_value_set
stub = _try_to_load_stub_cached(inference_state, import_names, python_value_set,
parent_module_context, sys_path)
parent_module_value, sys_path)
if stub is not None:
return ValueSet([stub])
return python_value_set
@@ -141,18 +144,18 @@ def _try_to_load_stub_cached(inference_state, import_names, *args, **kwargs):
def _try_to_load_stub(inference_state, import_names, python_value_set,
parent_module_context, sys_path):
parent_module_value, sys_path):
"""
Trying to load a stub for a set of import_names.
This is modelled to work like "PEP 561 -- Distributing and Packaging Type
Information", see https://www.python.org/dev/peps/pep-0561.
"""
if parent_module_context is None and len(import_names) > 1:
if parent_module_value is None and len(import_names) > 1:
try:
parent_module_context = _try_to_load_stub_cached(
parent_module_value = _try_to_load_stub_cached(
inference_state, import_names[:-1], NO_VALUES,
parent_module_context=None, sys_path=sys_path)
parent_module_value=None, sys_path=sys_path)
except KeyError:
pass
@@ -196,15 +199,15 @@ def _try_to_load_stub(inference_state, import_names, python_value_set,
return m
# 3. Try to load typeshed
m = _load_from_typeshed(inference_state, python_value_set, parent_module_context, import_names)
m = _load_from_typeshed(inference_state, python_value_set, parent_module_value, import_names)
if m is not None:
return m
# 4. Try to load pyi file somewhere if python_value_set was not defined.
if not python_value_set:
if parent_module_context is not None:
if parent_module_value is not None:
try:
method = parent_module_context.py__path__
method = parent_module_value.py__path__
except AttributeError:
check_path = []
else:
@@ -230,18 +233,18 @@ def _try_to_load_stub(inference_state, import_names, python_value_set,
return None
def _load_from_typeshed(inference_state, python_value_set, parent_module_context, import_names):
def _load_from_typeshed(inference_state, python_value_set, parent_module_value, import_names):
import_name = import_names[-1]
map_ = None
if len(import_names) == 1:
map_ = _cache_stub_file_map(inference_state.grammar.version_info)
import_name = _IMPORT_MAP.get(import_name, import_name)
elif isinstance(parent_module_context, ModuleContext):
if not parent_module_context.is_package:
elif isinstance(parent_module_value, ModuleValue):
if not parent_module_value.is_package:
# Only if it's a package (= a folder) something can be
# imported.
return None
path = parent_module_context.py__path__()
path = parent_module_value.py__path__()
map_ = _merge_create_stub_map(path)
if map_ is not None:

View File

@@ -295,9 +295,9 @@ class Importer(object):
value_set = ValueSet.from_sets([
self._inference_state.import_module(
import_names[:i+1],
parent_module_context,
parent_module_value,
sys_path
) for parent_module_context in value_set
) for parent_module_value in value_set
])
if not value_set:
message = 'No module named ' + '.'.join(import_names)
@@ -377,7 +377,7 @@ class Importer(object):
@plugin_manager.decorate()
@import_module_decorator
def import_module(inference_state, import_names, parent_module_context, sys_path):
def import_module(inference_state, import_names, parent_module_value, sys_path):
"""
This method is very similar to importlib's `_gcd_import`.
"""
@@ -388,7 +388,7 @@ def import_module(inference_state, import_names, parent_module_context, sys_path
return ValueSet([module])
module_name = '.'.join(import_names)
if parent_module_context is None:
if parent_module_value is None:
# Override the sys.path. It works only good that way.
# Injecting the path directly into `find_module` did not work.
file_io_or_ns, is_pkg = inference_state.compiled_subprocess.get_module_info(
@@ -401,7 +401,7 @@ def import_module(inference_state, import_names, parent_module_context, sys_path
return NO_VALUES
else:
try:
method = parent_module_context.py__path__
method = parent_module_value.py__path__
except AttributeError:
# The module is not a package.
return NO_VALUES
@@ -441,7 +441,7 @@ def import_module(inference_state, import_names, parent_module_context, sys_path
is_package=is_pkg,
)
if parent_module_context is None:
if parent_module_value is None:
debug.dbg('global search_module %s: %s', import_names[-1], module)
else:
debug.dbg('search_module %s in paths %s: %s', module_name, paths, module)