diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index e75690b5..ac1132be 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -31,7 +31,7 @@ from jedi.evaluate import representation as er from jedi.evaluate import imports from jedi.evaluate.param import try_iter_content from jedi.evaluate.helpers import get_module_names, evaluate_call_of_leaf -from jedi.evaluate.sys_path import get_venv_path +from jedi.evaluate.sys_path import get_venv_path, dotted_path_in_sys_path from jedi.evaluate.iterable import unpack_tuple_to_dict from jedi.evaluate.filters import TreeNameDefinition @@ -151,7 +151,10 @@ class Script(object): self._get_module_node(), self.path ) - imports.add_module(self._evaluator, module.name.string_name, module) + if self.path is not None: + name = dotted_path_in_sys_path(self._evaluator.sys_path, self.path) + if name is not None: + imports.add_module(self._evaluator, name, module) return module @property diff --git a/jedi/evaluate/compiled/mixed.py b/jedi/evaluate/compiled/mixed.py index 905f4da5..0be5007b 100644 --- a/jedi/evaluate/compiled/mixed.py +++ b/jedi/evaluate/compiled/mixed.py @@ -209,6 +209,7 @@ def _create(evaluator, obj, parent_context=None, *args): else: from jedi.evaluate.representation import ModuleContext module_context = ModuleContext(evaluator, module_node, path=path) + # TODO this __name__ is probably wrong. name = compiled_object.get_root_context().py__name__() imports.add_module(evaluator, name, module_context) diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index 2201f991..d0aec515 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -523,9 +523,11 @@ def get_modules_containing_name(evaluator, modules, name): with open(path, 'rb') as f: code = python_bytes_to_unicode(f.read(), errors='replace') if name in code: - module_name = os.path.basename(path)[:-3] # Remove `.py`. module = _load_module(evaluator, path, code) - add_module(evaluator, module_name, module) + + module_name = sys_path.dotted_path_in_sys_path(evaluator.sys_path, path) + if module_name is not None: + add_module(evaluator, module_name, module) return module # skip non python modules diff --git a/jedi/evaluate/sys_path.py b/jedi/evaluate/sys_path.py index 24bd26b6..a4990c3c 100644 --- a/jedi/evaluate/sys_path.py +++ b/jedi/evaluate/sys_path.py @@ -1,6 +1,7 @@ import glob import os import sys +import imp from jedi.evaluate.site import addsitedir from jedi._compatibility import exec_function, unicode @@ -281,3 +282,33 @@ def _get_buildout_script_paths(module_path): debug.warning(unicode(e)) continue return extra_module_paths + + +def dotted_path_in_sys_path(sys_path, module_path): + """ + Returns the dotted path inside a sys.path. + """ + # First remove the suffix. + for suffix, _, _ in imp.get_suffixes(): + if module_path.endswith(suffix): + module_path = module_path[:-len(suffix)] + break + else: + # There should always be a suffix in a valid Python file on the path. + return None + + if module_path.startswith(os.path.sep): + # The paths in sys.path most of the times don't end with a slash. + module_path = module_path[1:] + + for p in sys_path: + if module_path.startswith(p): + rest = module_path[len(p):] + if rest: + split = rest.split(os.path.sep) + for string in split: + if not string or '.' in string: + return None + return '.'.join(split) + + return None