Fix a goto case with nested pyi files

This commit is contained in:
Dave Halter
2019-12-15 17:37:24 +01:00
parent 35442eff81
commit 6e2a76feb9
5 changed files with 56 additions and 36 deletions

View File

@@ -107,12 +107,9 @@ class InferenceState(object):
self.reset_recursion_limitations() self.reset_recursion_limitations()
def import_module(self, import_names, parent_module_value=None, def import_module(self, import_names, sys_path=None, prefer_stubs=True):
sys_path=None, prefer_stubs=True): return imports.import_module_by_names(
if sys_path is None: self, import_names, sys_path, prefer_stubs=prefer_stubs)
sys_path = self.get_sys_path()
return imports.import_module(self, import_names, parent_module_value,
sys_path, prefer_stubs=prefer_stubs)
@staticmethod @staticmethod
@plugin_manager.decorate() @plugin_manager.decorate()

View File

@@ -391,6 +391,7 @@ class DirectObjectAccess(object):
except AttributeError: except AttributeError:
pass pass
else: else:
if module is not None:
try: try:
__import__(module) __import__(module)
# For some modules like _sqlite3, the __module__ for classes is # For some modules like _sqlite3, the __module__ for classes is

View File

@@ -288,26 +288,11 @@ class Importer(object):
if not self.import_path or not self._infer_possible: if not self.import_path or not self._infer_possible:
return NO_VALUES return NO_VALUES
import_names = tuple(
force_unicode(i.value if isinstance(i, tree.Name) else i)
for i in self.import_path
)
sys_path = self._sys_path_with_modifications(is_completion=False) sys_path = self._sys_path_with_modifications(is_completion=False)
value_set = [None] return import_module_by_names(
for i, name in enumerate(self.import_path): self._inference_state, self.import_path, sys_path, self._module_context
value_set = ValueSet.from_sets([ )
self._inference_state.import_module(
import_names[:i+1],
parent_module_value,
sys_path
) for parent_module_value in value_set
])
if not value_set:
message = 'No module named ' + '.'.join(import_names)
_add_error(self._module_context, name, message)
return NO_VALUES
return value_set
def _get_module_names(self, search_path=None, in_module=None): def _get_module_names(self, search_path=None, in_module=None):
""" """
@@ -381,6 +366,36 @@ class Importer(object):
return names return names
def import_module_by_names(inference_state, import_names, sys_path=None,
module_context=None, prefer_stubs=True):
if sys_path is None:
sys_path = inference_state.get_sys_path()
str_import_names = tuple(
force_unicode(i.value if isinstance(i, tree.Name) else i)
for i in import_names
)
value_set = [None]
for i, name in enumerate(import_names):
value_set = ValueSet.from_sets([
import_module(
inference_state,
str_import_names[:i+1],
parent_module_value,
sys_path,
prefer_stubs=prefer_stubs,
) for parent_module_value in value_set
])
if not value_set:
message = 'No module named ' + '.'.join(str_import_names)
if module_context is not None:
_add_error(module_context, name, message)
else:
debug.warning(message)
return NO_VALUES
return value_set
@plugin_manager.decorate() @plugin_manager.decorate()
@import_module_decorator @import_module_decorator
def import_module(inference_state, import_names, parent_module_value, sys_path): def import_module(inference_state, import_names, parent_module_value, sys_path):

View File

@@ -14,3 +14,10 @@ def test_sqlite3_conversion(Script):
d, = script1.goto_definitions(only_stubs=True) d, = script1.goto_definitions(only_stubs=True)
assert d.is_stub() assert d.is_stub()
assert d.full_name == 'sqlite3.dbapi2.Connection' assert d.full_name == 'sqlite3.dbapi2.Connection'
script2 = Script(path=d.module_path, line=d.line, column=d.column)
d, = script2.goto_definitions()
assert not d.is_stub()
assert d.full_name == 'sqlite3.Connection'
v, = d._name.infer()
assert v.is_compiled()

View File

@@ -28,12 +28,12 @@ from test.helpers import root_dir
{'goto_has_python': True}], {'goto_has_python': True}],
['from keyword import kwlist; kwlist', 'typing.Sequence', True, True, ['from keyword import kwlist; kwlist', 'typing.Sequence', True, True,
{'full_name': 'keyword.kwlist'}], {'goto_full_name': 'keyword.kwlist'}],
['from keyword import kwlist', 'typing.Sequence', True, True, ['from keyword import kwlist', 'typing.Sequence', True, True,
{'full_name': 'keyword.kwlist'}], {'goto_full_name': 'keyword.kwlist'}],
['from socket import AF_INET', 'socket.AddressFamily', True, False, ['from socket import AF_INET', 'socket.AddressFamily', True, False,
{'full_name': 'socket.AF_INET'}], {'goto_full_name': 'socket.AF_INET'}],
['from socket import socket', 'socket.socket', True, True, {}], ['from socket import socket', 'socket.socket', True, True, {}],
['import with_stub', 'with_stub', True, True, {}], ['import with_stub', 'with_stub', True, True, {}],