Fix get_modules_containing_name

This commit is contained in:
Dave Halter
2018-12-22 14:33:24 +01:00
parent fcda3f7bc5
commit ca784916bb
3 changed files with 55 additions and 26 deletions

View File

@@ -143,7 +143,7 @@ class ModuleContext(ModuleMixin, TreeContext):
tree_node=module_node
)
self._path = path
self._string_names = string_names
self.string_names = string_names
self.code_lines = code_lines
def _get_init_directory(self):
@@ -160,9 +160,9 @@ class ModuleContext(ModuleMixin, TreeContext):
return None
def py__name__(self):
if self._string_names is None:
if self.string_names is None:
return None
return '.'.join(self._string_names)
return '.'.join(self.string_names)
def py__file__(self):
"""

View File

@@ -497,18 +497,14 @@ def get_modules_containing_name(evaluator, modules, name):
"""
Search a name in the directories of modules.
"""
def check_directories(paths):
for p in paths:
if p is not None:
# We need abspath, because the seetings paths might not already
# have been converted to absolute paths.
d = os.path.dirname(os.path.abspath(p))
for file_name in os.listdir(d):
path = os.path.join(d, file_name)
if file_name.endswith('.py'):
yield path
def check_directory(path):
d = os.path.dirname(os.path.abspath(path))
for file_name in os.listdir(d):
path = os.path.join(d, file_name)
if file_name.endswith('.py'):
yield path
def check_fs(path):
def check_fs(path, base_names):
try:
f = open(path, 'rb')
except FileNotFoundError:
@@ -517,7 +513,15 @@ def get_modules_containing_name(evaluator, modules, name):
code = python_bytes_to_unicode(f.read(), errors='replace')
if name in code:
e_sys_path = evaluator.get_sys_path()
import_names = sys_path.calculate_dotted_path_from_sys_path(e_sys_path, path)
module_name = os.path.basename(path)
if module_name.endswith('.py'):
module_name = module_name[:-3]
if base_names:
import_names = base_names + (module_name,)
else:
import_names = sys_path.calculate_dotted_path_from_sys_path(e_sys_path, path)
module = _load_module(
evaluator, path, code,
sys_path=e_sys_path,
@@ -528,26 +532,32 @@ def get_modules_containing_name(evaluator, modules, name):
# skip non python modules
used_mod_paths = set()
path_with_names_to_be_checked = []
for m in modules:
try:
path = m.py__file__()
except AttributeError:
pass
else:
used_mod_paths.add(path)
if path is not None:
if path not in used_mod_paths:
used_mod_paths.add(path)
string_names = m.string_names
if not m.is_package() and string_names is not None:
string_names = string_names[:-1]
path_with_names_to_be_checked.append((path, string_names))
yield m
if not settings.dynamic_params_for_other_modules:
return
additional = set(os.path.abspath(p) for p in settings.additional_dynamic_modules)
# Check the directories of used modules.
paths = (additional | set(check_directories(used_mod_paths))) \
- used_mod_paths
for p in settings.additional_dynamic_modules:
p = os.path.abspath(p)
if p not in used_mod_paths:
path_with_names_to_be_checked.append((p, None))
# Sort here to make issues less random.
for p in sorted(paths):
# make testing easier, sort it - same results on every interpreter
m = check_fs(p)
if m is not None and not isinstance(m, compiled.CompiledObject):
yield m
for p, base_names in path_with_names_to_be_checked:
for file_path in check_directory(p):
m = check_fs(file_path, base_names)
if m is not None and not isinstance(m, compiled.CompiledObject):
yield m

View File

@@ -9,6 +9,7 @@ import pytest
from jedi._compatibility import find_module_py33, find_module
from jedi.evaluate import compiled
from jedi.evaluate import imports
from ..helpers import cwd_at
@@ -251,3 +252,21 @@ def test_compiled_import_none(monkeypatch, Script):
"""
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
assert not Script('import sys').goto_definitions()
@pytest.mark.parametrize(
('path', 'goal'), [
('test_evaluate/test_docstring.py', ('ok', 'lala', 'test_imports')),
('test_evaluate/__init__.py', ('ok', 'lala', 'x', 'test_imports')),
]
)
def test_get_modules_containing_name(evaluator, path, goal):
module = imports._load_module(evaluator, path, import_names=('ok', 'lala', 'x'))
assert module
input_module, found_module = imports.get_modules_containing_name(
evaluator,
[module],
'string_that_only_exists_here'
)
assert input_module is module
assert found_module.string_names == goal