mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Relative imports should work even if they are not within the project
This commit is contained in:
@@ -245,7 +245,38 @@ class Importer:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def follow(self):
|
def follow(self):
|
||||||
if not self.import_path or not self._infer_possible:
|
if not self.import_path:
|
||||||
|
if self._fixed_sys_path:
|
||||||
|
# This is a bit of a special case, that maybe should be
|
||||||
|
# revisited. If the project path is wrong or the user uses
|
||||||
|
# relative imports the wrong way, we might end up here, where
|
||||||
|
# the `fixed_sys_path == project.path` in that case we kind of
|
||||||
|
# use the project.path.parent directory as our path. This is
|
||||||
|
# usually not a problem, except if imorts in other places are
|
||||||
|
# using the same names. Example:
|
||||||
|
#
|
||||||
|
# foo/ < #1
|
||||||
|
# - setup.py
|
||||||
|
# - foo/ < #2
|
||||||
|
# - __init__.py
|
||||||
|
# - foo.py < #3
|
||||||
|
#
|
||||||
|
# If the top foo is our project folder and somebody uses
|
||||||
|
# `from . import foo` in `setup.py`, it will resolve to foo #2,
|
||||||
|
# which means that the import for foo.foo is cached as
|
||||||
|
# `__init__.py` (#2) and not as `foo.py` (#3). This is usually
|
||||||
|
# not an issue, because this case is probably pretty rare, but
|
||||||
|
# might be an issue for some people.
|
||||||
|
from jedi.inference.value.namespace import ImplicitNamespaceValue
|
||||||
|
import_path = (os.path.basename(self._fixed_sys_path[0]),)
|
||||||
|
ns = ImplicitNamespaceValue(
|
||||||
|
self._inference_state,
|
||||||
|
string_names=import_path,
|
||||||
|
paths=self._fixed_sys_path,
|
||||||
|
)
|
||||||
|
return ValueSet({ns})
|
||||||
|
return NO_VALUES
|
||||||
|
if not self._infer_possible:
|
||||||
return NO_VALUES
|
return NO_VALUES
|
||||||
|
|
||||||
# Check caches first
|
# Check caches first
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import pytest
|
|||||||
|
|
||||||
def test_import_references(Script):
|
def test_import_references(Script):
|
||||||
s = Script("from .. import foo", path="foo.py")
|
s = Script("from .. import foo", path="foo.py")
|
||||||
assert [usage.line for usage in s.get_references(line=1, column=18)] == [1]
|
assert [usage.line for usage in s.get_references()] == [1]
|
||||||
|
|
||||||
|
|
||||||
def test_exclude_builtin_modules(Script):
|
def test_exclude_builtin_modules(Script):
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
import jedi
|
||||||
from jedi.file_io import FileIO
|
from jedi.file_io import FileIO
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
@@ -468,3 +469,23 @@ def test_relative_import_star(Script):
|
|||||||
script = Script(source, path='export.py')
|
script = Script(source, path='export.py')
|
||||||
|
|
||||||
assert script.complete(3, len("furl.c"))
|
assert script.complete(3, len("furl.c"))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('with_init', [False, True])
|
||||||
|
def test_relative_imports_without_path_and_setup_py(
|
||||||
|
Script, inference_state, environment, tmpdir, with_init):
|
||||||
|
# Contrary to other tests here we create a temporary folder that is not
|
||||||
|
# part of a folder with a setup py that signifies
|
||||||
|
tmpdir.join('file1.py').write('do_foo = 1')
|
||||||
|
other_path = tmpdir.join('other_files')
|
||||||
|
other_path.join('file2.py').write('def do_nothing():\n pass', ensure=True)
|
||||||
|
if with_init:
|
||||||
|
other_path.join('__init__.py').write('')
|
||||||
|
|
||||||
|
for name, code in [('file2', 'from . import file2'),
|
||||||
|
('file1', 'from .. import file1')]:
|
||||||
|
for func in (jedi.Script.goto, jedi.Script.infer):
|
||||||
|
n, = func(Script(code, path=other_path.join('test1.py').strpath))
|
||||||
|
assert n.name == name
|
||||||
|
assert n.type == 'module'
|
||||||
|
assert n.line == 1
|
||||||
|
|||||||
Reference in New Issue
Block a user