diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 934b29d6..76771669 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -589,6 +589,7 @@ def search_in_module(inference_state, module_context, names, wanted_names, module_context, n.infer() ) + debug.dbg('dot lookup on search %s from %s', new_names, names[:10]) names = new_names last_name = wanted_names[-1].lower() diff --git a/jedi/api/project.py b/jedi/api/project.py index 5d947cf3..49c335f4 100644 --- a/jedi/api/project.py +++ b/jedi/api/project.py @@ -5,6 +5,7 @@ import sys from jedi._compatibility import FileNotFoundError, PermissionError, \ IsADirectoryError, scandir +from jedi import debug from jedi.api.environment import get_cached_default_environment, create_environment from jedi.api.exceptions import WrongVersion from jedi.api.completion import search_in_module @@ -15,8 +16,6 @@ from jedi.inference.imports import load_module_from_path, \ from jedi.inference.sys_path import discover_buildout_paths 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.value.module import ModuleValue -from jedi.inference import InferenceState from jedi.file_io import FolderIO, FileIO from jedi.common.utils import traverse_parents @@ -189,6 +188,7 @@ class Project(object): raise NotImplementedError( "No support for refactorings/search on Python 2/3.5" ) + debug.dbg('Search for string %s', string) wanted_type, wanted_names = split_search_string(string) name = wanted_names[0] @@ -219,6 +219,7 @@ class Project(object): else: continue + debug.dbg('Search of a specific module %s', m) for x in search_in_module( inference_state, m, @@ -250,7 +251,6 @@ class Project(object): # folders. if not p.startswith(self._path) ] - names = list(iter_module_names(inference_state, empty_module_context, sys_path)) for x in search_in_module( inference_state, @@ -258,7 +258,7 @@ class Project(object): names=names, wanted_type=wanted_type, wanted_names=wanted_names, - complete=complete + complete=complete, ): yield x # Python 2... diff --git a/jedi/inference/imports.py b/jedi/inference/imports.py index 91887f99..c1ec688d 100644 --- a/jedi/inference/imports.py +++ b/jedi/inference/imports.py @@ -428,13 +428,19 @@ def import_module(inference_state, import_names, parent_module_value, sys_path): def _load_python_module(inference_state, file_io, import_names=None, is_package=False): + is_stub = file_io.path.endswith('.pyi') module_node = inference_state.parse( file_io=file_io, cache=True, diff_cache=settings.fast_parser, - cache_path=settings.cache_directory + cache_path=settings.cache_directory, + use_latest_grammar=is_stub, ) + from jedi.inference.gradual.typeshed import create_stub_module + if is_stub: + return create_stub_module( + inference_state, NO_VALUES, module_node, file_io, import_names) from jedi.inference.value import ModuleValue return ModuleValue( inference_state, module_node, diff --git a/jedi/inference/sys_path.py b/jedi/inference/sys_path.py index 5234ac2c..81b14624 100644 --- a/jedi/inference/sys_path.py +++ b/jedi/inference/sys_path.py @@ -207,7 +207,7 @@ def _get_buildout_script_paths(search_path): def remove_python_path_suffix(path): - for suffix in all_suffixes(): + for suffix in all_suffixes() + ['.pyi']: if path.endswith(suffix): path = path[:-len(suffix)] break diff --git a/test/test_api/test_project.py b/test/test_api/test_project.py index e6d27847..b86d5813 100644 --- a/test/test_api/test_project.py +++ b/test/test_api/test_project.py @@ -89,10 +89,21 @@ def test_load_save_project(tmpdir): 'examples.implicit_namespace_package.ns2'], dict(complete=True)), + # With namespace & stub + ('with_python.module', ['examples.stub_packages.with_python.module'], {}), + ('with_python.modul', ['examples.stub_packages.with_python.module'], + dict(complete=True)), + ('no_python.module', ['stub:examples.stub_packages.no_python.module'], {}), + ('no_python.modul', ['stub:examples.stub_packages.no_python.module'], + dict(complete=True)), + ('with_python-stubs.module', ['stub:examples.stub_packages.with_python-stubs.module'], {}), + ('no_python-stubs.module', ['stub:examples.stub_packages.no_python-stubs.module'], {}), + # On sys path ('sys.path', ['stub:sys.path'], {}), ('json.dumps', ['stub:json.dumps', 'json.dumps'], {}), # stdlib + stub - ('multiprocessing', ['stub:multiprocessing'], {}) + ('multiprocessing', ['stub:multiprocessing'], {}), + ('multiprocessin', ['stub:multiprocessing'], dict(complete=True)), ] ) @pytest.mark.skipif(sys.version_info < (3, 6), reason="Ignore Python 2, because EOL")