diff --git a/jedi/inference/gradual/conversion.py b/jedi/inference/gradual/conversion.py index 074e29a7..541aa0d1 100644 --- a/jedi/inference/gradual/conversion.py +++ b/jedi/inference/gradual/conversion.py @@ -73,7 +73,13 @@ def _try_stub_to_python_names(names, prefer_stub_to_compiled=False): converted_names = converted.goto(name.get_public_name()) if converted_names: for n in converted_names: - yield n + if n.get_root_context().is_stub(): + # If it's a stub again, it means we're going in + # a circle. Probably some imports make it a + # stub again. + yield name + else: + yield n continue yield name diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 39ccb0da..7d5d183f 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -431,8 +431,9 @@ def test_completion_cache(Script, module_injector): assert cls.docstring() == 'foo()\n\ndoc2' -def test_typing_module_completions(Script): - for c in Script('import typing; typing.').completions(): +@pytest.mark.parametrize('module', ['typing', 'os']) +def test_module_completions(Script, module): + for c in Script('import {module}; {module}.'.format(module=module)).completions(): # Just make sure that there are no errors c.type c.docstring() diff --git a/test/test_inference/test_gradual/test_conversion.py b/test/test_inference/test_gradual/test_conversion.py index 123858d6..b63129ae 100644 --- a/test/test_inference/test_gradual/test_conversion.py +++ b/test/test_inference/test_gradual/test_conversion.py @@ -62,3 +62,11 @@ def test_goto_import(Script, skip_pre_python35): assert d.is_stub() d, = Script(code).goto() assert not d.is_stub() + + +def test_os_stat_result(Script): + d, = Script('import os; os.stat_result').goto() + assert d.is_stub() + n = d._name + # This should not be a different stub name + assert convert_names([n]) == [n]