1
0
forked from VimPlug/jedi

The calculation of dotted paths from normal paths was completely wrong

This commit is contained in:
Dave Halter
2019-02-28 09:42:30 +01:00
parent 17136e03d2
commit 1a32663f85
4 changed files with 44 additions and 12 deletions

View File

@@ -32,7 +32,7 @@ from jedi.evaluate import imports
from jedi.evaluate import usages
from jedi.evaluate.arguments import try_iter_content
from jedi.evaluate.helpers import get_module_names, evaluate_call_of_leaf
from jedi.evaluate.sys_path import dotted_path_in_sys_path
from jedi.evaluate.sys_path import transform_path_to_dotted
from jedi.evaluate.filters import TreeNameDefinition, ParamName
from jedi.evaluate.syntax_tree import tree_name_to_contexts
from jedi.evaluate.context import ModuleContext
@@ -107,7 +107,6 @@ class Script(object):
self._evaluator = Evaluator(
project, environment=environment, script_path=self.path
)
self._project = project
debug.speed('init')
self._module_node, source = self._evaluator.parse_and_get_code(
code=source,
@@ -145,7 +144,7 @@ class Script(object):
def _get_module(self):
name = '__main__'
if self.path is not None:
import_names = dotted_path_in_sys_path(self._evaluator.get_sys_path(), self.path)
import_names = transform_path_to_dotted(self._evaluator.get_sys_path(), self.path)
if import_names is not None:
name = '.'.join(import_names)

View File

@@ -559,7 +559,7 @@ 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.dotted_path_in_sys_path(e_sys_path, path)
import_names = sys_path.transform_path_to_dotted(e_sys_path, path)
module = _load_module(
evaluator, path, code,
sys_path=e_sys_path,

View File

@@ -196,9 +196,14 @@ def _get_buildout_script_paths(search_path):
continue
def dotted_path_in_sys_path(sys_path, module_path):
def transform_path_to_dotted(sys_path, module_path):
"""
Returns the dotted path inside a sys.path as a list of names.
Returns the dotted path inside a sys.path as a list of names. e.g.
>>> calculate_dotted_from_path(["/foo"], '/foo/bar/baz.py')
['bar', 'baz']
Returns None if the path doesn't really resolve to anything.
"""
# First remove the suffix.
for suffix in all_suffixes():
@@ -209,17 +214,17 @@ def dotted_path_in_sys_path(sys_path, module_path):
# 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.startswith(os.path.sep):
# Remove a slash in cases it's still there.
rest = rest[1:]
if rest:
split = rest.split(os.path.sep)
for string in split:
if not string or '.' in string:
if not string:
return None
return split

View File

@@ -3,6 +3,8 @@ from glob import glob
import sys
import shutil
import pytest
from jedi.evaluate import sys_path
from jedi.api.environment import create_environment
@@ -59,3 +61,29 @@ def test_venv_and_pths(venv_path):
# Ensure that none of venv dirs leaked to the interpreter.
assert not set(sys.path).intersection(ETALON)
_s = ['/a', '/b', '/c/d/']
@pytest.mark.parametrize(
'sys_path_, module_path, result', [
(_s, '/a/b', None),
(_s, '/a/b/c', None),
(_s, '/a/b.py', ['b']),
(_s, '/a/b/c.py', ['b', 'c']),
(_s, '/x/b.py', None),
(_s, '/c/d/x.py', ['x']),
(_s, '/c/d/x.py', ['x']),
(_s, '/c/d/x/y.py', ['x', 'y']),
# If dots are in there they also resolve. These are obviously illegal
# in Python, but Jedi can handle them. Give the user a bit more freedom
# that he will have to correct eventually.
(_s, '/a/b.c.py', ['b.c']),
(_s, '/a/b.d/foo.bar.py', ['b.d', 'foo.bar']),
(_s, '/a/.py', None),
(_s, '/a/c/.py', None),
])
def test_calculate_dotted_from_path(sys_path_, module_path, result):
assert sys_path.transform_path_to_dotted(sys_path_, module_path) == result