forked from VimPlug/jedi
Try to fix a few more stub issues in search
This commit is contained in:
@@ -19,7 +19,7 @@ from jedi.inference.base_value import ValueSet
|
|||||||
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
||||||
from jedi.inference.context import get_global_filters
|
from jedi.inference.context import get_global_filters
|
||||||
from jedi.inference.value import TreeInstance, ModuleValue
|
from jedi.inference.value import TreeInstance, ModuleValue
|
||||||
from jedi.inference.names import ParamNameWrapper
|
from jedi.inference.names import ParamNameWrapper, SubModuleName
|
||||||
from jedi.inference.gradual.conversion import convert_values, convert_names
|
from jedi.inference.gradual.conversion import convert_values, convert_names
|
||||||
from jedi.parser_utils import cut_value_at_position
|
from jedi.parser_utils import cut_value_at_position
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
@@ -597,7 +597,10 @@ def search_in_module(inference_state, module_context, names, wanted_names,
|
|||||||
string = n.string_name.lower()
|
string = n.string_name.lower()
|
||||||
if complete and helpers.match(string, last_name, fuzzy=fuzzy) \
|
if complete and helpers.match(string, last_name, fuzzy=fuzzy) \
|
||||||
or not complete and string == last_name:
|
or not complete and string == last_name:
|
||||||
names = [n]
|
if isinstance(n, SubModuleName):
|
||||||
|
names = [v.name for v in n.infer()]
|
||||||
|
else:
|
||||||
|
names = [n]
|
||||||
if convert:
|
if convert:
|
||||||
names = convert_names(names)
|
names = convert_names(names)
|
||||||
for n2 in names:
|
for n2 in names:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from jedi.inference.imports import load_module_from_path, \
|
|||||||
from jedi.inference.sys_path import discover_buildout_paths
|
from jedi.inference.sys_path import discover_buildout_paths
|
||||||
from jedi.inference.cache import inference_state_as_method_param_cache
|
from jedi.inference.cache import inference_state_as_method_param_cache
|
||||||
from jedi.inference.references import recurse_find_python_folders_and_files, search_in_file_ios
|
from jedi.inference.references import recurse_find_python_folders_and_files, search_in_file_ios
|
||||||
from jedi.file_io import FolderIO, FileIO
|
from jedi.file_io import FolderIO
|
||||||
from jedi.common.utils import traverse_parents
|
from jedi.common.utils import traverse_parents
|
||||||
|
|
||||||
_CONFIG_FOLDER = '.jedi'
|
_CONFIG_FOLDER = '.jedi'
|
||||||
@@ -25,6 +25,23 @@ _CONTAINS_POTENTIAL_PROJECT = 'setup.py', '.git', '.hg', 'requirements.txt', 'MA
|
|||||||
_SERIALIZER_VERSION = 1
|
_SERIALIZER_VERSION = 1
|
||||||
|
|
||||||
|
|
||||||
|
def _try_to_skip_duplicates(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
found_tree_nodes = []
|
||||||
|
found_modules = []
|
||||||
|
for definition in func(*args, **kwargs):
|
||||||
|
tree_node = definition._name.tree_name
|
||||||
|
if tree_node is not None and tree_node in found_tree_nodes:
|
||||||
|
continue
|
||||||
|
if definition.type == 'module' and definition.module_path is not None:
|
||||||
|
if definition.module_path in found_modules:
|
||||||
|
continue
|
||||||
|
found_modules.append(definition.module_path)
|
||||||
|
yield definition
|
||||||
|
found_tree_nodes.append(tree_node)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def _remove_duplicates_from_path(path):
|
def _remove_duplicates_from_path(path):
|
||||||
used = set()
|
used = set()
|
||||||
for p in path:
|
for p in path:
|
||||||
@@ -174,6 +191,7 @@ class Project(object):
|
|||||||
self._environment = get_cached_default_environment()
|
self._environment = get_cached_default_environment()
|
||||||
return self._environment
|
return self._environment
|
||||||
|
|
||||||
|
@_try_to_skip_duplicates
|
||||||
def search(self, string, complete=False, all_scopes=False):
|
def search(self, string, complete=False, all_scopes=False):
|
||||||
"""
|
"""
|
||||||
Returns a generator of names
|
Returns a generator of names
|
||||||
@@ -215,7 +233,7 @@ class Project(object):
|
|||||||
else:
|
else:
|
||||||
file_ios.append(file_io)
|
file_ios.append(file_io)
|
||||||
file_name = os.path.basename(file_io.path)
|
file_name = os.path.basename(file_io.path)
|
||||||
if file_name in (name + '.py', name + 'pyi'):
|
if file_name in (name + '.py', name + '.pyi'):
|
||||||
m = load_module_from_path(inference_state, file_io).as_context()
|
m = load_module_from_path(inference_state, file_io).as_context()
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
@@ -229,16 +247,19 @@ class Project(object):
|
|||||||
wanted_names=wanted_names,
|
wanted_names=wanted_names,
|
||||||
complete=complete,
|
complete=complete,
|
||||||
convert=True,
|
convert=True,
|
||||||
|
ignore_imports=True,
|
||||||
):
|
):
|
||||||
yield x # Python 2...
|
yield x # Python 2...
|
||||||
|
|
||||||
# 2. Search for identifiers in the project.
|
# 2. Search for identifiers in the project.
|
||||||
for module_context in search_in_file_ios(inference_state, file_ios, name):
|
for module_context in search_in_file_ios(inference_state, file_ios, name):
|
||||||
names = get_module_names(module_context.tree_node, all_scopes=all_scopes)
|
names = get_module_names(module_context.tree_node, all_scopes=all_scopes)
|
||||||
|
names = [module_context.create_name(n) for n in names]
|
||||||
|
names = _remove_imports(names)
|
||||||
for x in search_in_module(
|
for x in search_in_module(
|
||||||
inference_state,
|
inference_state,
|
||||||
module_context,
|
module_context,
|
||||||
names=[module_context.create_name(n) for n in names],
|
names=names,
|
||||||
wanted_type=wanted_type,
|
wanted_type=wanted_type,
|
||||||
wanted_names=wanted_names,
|
wanted_names=wanted_names,
|
||||||
complete=complete,
|
complete=complete,
|
||||||
@@ -327,10 +348,8 @@ def get_default_project(path=None):
|
|||||||
return Project(curdir)
|
return Project(curdir)
|
||||||
|
|
||||||
|
|
||||||
def _get_sys_path_folder_and_file_ios(sys_path):
|
def _remove_imports(names):
|
||||||
for p in sys_path:
|
return [
|
||||||
for dir_entry in scandir(p):
|
n for n in names
|
||||||
if dir_entry.is_dir():
|
if n.tree_name is None or n.api_type != 'module'
|
||||||
yield FolderIO(p), None
|
]
|
||||||
else:
|
|
||||||
yield None, FileIO(p)
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import os
|
|||||||
from parso.python import tree
|
from parso.python import tree
|
||||||
from parso.tree import search_ancestor
|
from parso.tree import search_ancestor
|
||||||
|
|
||||||
from jedi._compatibility import ImplicitNSInfo, force_unicode
|
from jedi._compatibility import ImplicitNSInfo, force_unicode, FileNotFoundError
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.parser_utils import get_cached_code_lines
|
from jedi.parser_utils import get_cached_code_lines
|
||||||
@@ -28,7 +28,7 @@ from jedi.inference.utils import unite
|
|||||||
from jedi.inference.cache import inference_state_method_cache
|
from jedi.inference.cache import inference_state_method_cache
|
||||||
from jedi.inference.names import ImportName, SubModuleName
|
from jedi.inference.names import ImportName, SubModuleName
|
||||||
from jedi.inference.base_value import ValueSet, NO_VALUES
|
from jedi.inference.base_value import ValueSet, NO_VALUES
|
||||||
from jedi.inference.gradual.typeshed import import_module_decorator
|
from jedi.inference.gradual.typeshed import import_module_decorator, create_stub_module
|
||||||
from jedi.inference.value.module import iter_module_names as module_iter_module_names
|
from jedi.inference.value.module import iter_module_names as module_iter_module_names
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
@@ -437,10 +437,18 @@ def _load_python_module(inference_state, file_io,
|
|||||||
use_latest_grammar=is_stub,
|
use_latest_grammar=is_stub,
|
||||||
)
|
)
|
||||||
|
|
||||||
from jedi.inference.gradual.typeshed import create_stub_module
|
|
||||||
if is_stub:
|
if is_stub:
|
||||||
|
folder_io = file_io.get_parent_folder()
|
||||||
|
python_file_io = folder_io.get_file_io(import_names[-1] + '.py')
|
||||||
|
try:
|
||||||
|
v = load_module_from_path(inference_state, python_file_io, import_names[:-1])
|
||||||
|
values = ValueSet([v])
|
||||||
|
except FileNotFoundError:
|
||||||
|
values = NO_VALUES
|
||||||
|
|
||||||
return create_stub_module(
|
return create_stub_module(
|
||||||
inference_state, NO_VALUES, module_node, file_io, import_names)
|
inference_state, values, module_node, file_io, import_names)
|
||||||
|
|
||||||
from jedi.inference.value import ModuleValue
|
from jedi.inference.value import ModuleValue
|
||||||
return ModuleValue(
|
return ModuleValue(
|
||||||
inference_state, module_node,
|
inference_state, module_node,
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ class ImplicitNamespaceValue(Value, SubModuleDictMixin):
|
|||||||
def get_filters(self, origin_scope=None):
|
def get_filters(self, origin_scope=None):
|
||||||
yield DictFilter(self.sub_modules_dict())
|
yield DictFilter(self.sub_modules_dict())
|
||||||
|
|
||||||
|
def get_qualified_names(self):
|
||||||
|
return ()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@inference_state_method_cache()
|
@inference_state_method_cache()
|
||||||
def name(self):
|
def name(self):
|
||||||
|
|||||||
@@ -90,17 +90,27 @@ def test_load_save_project(tmpdir):
|
|||||||
dict(complete=True)),
|
dict(complete=True)),
|
||||||
|
|
||||||
# With namespace & stub
|
# With namespace & stub
|
||||||
('with_python.module', ['examples.stub_packages.with_python.module'], {}),
|
('with_python.module', ['stub:examples.stub_packages.with_python.module',
|
||||||
('with_python.modul', ['examples.stub_packages.with_python.module'],
|
'examples.stub_packages.with_python.module'], {}),
|
||||||
|
('with_python.modul', ['stub:examples.stub_packages.with_python.module',
|
||||||
|
'examples.stub_packages.with_python.module'],
|
||||||
dict(complete=True)),
|
dict(complete=True)),
|
||||||
('no_python.foo', ['stub:examples.stub_packages.no_python.foo'], {}),
|
('no_python.foo', ['stub:examples.stub_packages.no_python.foo'], {}),
|
||||||
('no_python.fo', ['stub:examples.stub_packages.no_python.foo'],
|
('no_python.fo', ['stub:examples.stub_packages.no_python.foo'],
|
||||||
dict(complete=True)),
|
dict(complete=True)),
|
||||||
('with_python-stubs.module', [], {}),
|
('with_python-stubs.module', [], {}),
|
||||||
('no_python-stubs.foo', [], {}),
|
('no_python-stubs.foo', [], {}),
|
||||||
('with_python', ['stub:examples.stub_packages.with_python', 'examples.stub_packages.with_python'], {}),
|
# Both locations are given, because they live in separate folders (one
|
||||||
|
# suffixed with -stubs.
|
||||||
|
('with_python', ['stub:examples.stub_packages.with_python',
|
||||||
|
'examples.stub_packages.with_python'], {}),
|
||||||
('no_python', ['stub:examples.stub_packages.no_python'], {}),
|
('no_python', ['stub:examples.stub_packages.no_python'], {}),
|
||||||
|
|
||||||
|
('stub_only', ['stub:completion.stub_folder.stub_only',
|
||||||
|
'stub:examples.stub_packages.with_python.stub_only'], {}),
|
||||||
|
('with_stub', ['completion.stub_folder.with_stub'], {}),
|
||||||
|
|
||||||
|
|
||||||
# On sys path
|
# On sys path
|
||||||
('sys.path', ['stub:sys.path'], {}),
|
('sys.path', ['stub:sys.path'], {}),
|
||||||
('json.dumps', ['json.dumps'], {}), # stdlib + stub
|
('json.dumps', ['json.dumps'], {}), # stdlib + stub
|
||||||
|
|||||||
Reference in New Issue
Block a user