mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Finished changing the import logic. The sys.path calculations within Jedi are clearer now.
This commit is contained in:
@@ -284,7 +284,7 @@ class Script(object):
|
||||
if eval_stmt is None:
|
||||
return []
|
||||
|
||||
module = self._parser.module()
|
||||
module = self._evaluator.wrap(self._parser.module())
|
||||
names, level, _, _ = helpers.check_error_statements(module, self._pos)
|
||||
if names:
|
||||
names = [str(n) for n in names]
|
||||
|
||||
@@ -74,6 +74,9 @@ class CompiledObject(Base):
|
||||
def py__bool__(self):
|
||||
return bool(self.obj)
|
||||
|
||||
def py__file__(self):
|
||||
return self.obj.__file__
|
||||
|
||||
def is_class(self):
|
||||
return inspect.isclass(self.obj)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ from jedi import debug
|
||||
from jedi import cache
|
||||
from jedi.parser import fast
|
||||
from jedi.parser import tree as pr
|
||||
from jedi.evaluate.sys_path import get_sys_path, sys_path_with_modifications
|
||||
from jedi.evaluate import sys_path
|
||||
from jedi.evaluate import helpers
|
||||
from jedi import settings
|
||||
from jedi.common import source_to_unicode
|
||||
@@ -213,9 +213,11 @@ class _Importer(object):
|
||||
self._evaluator = evaluator
|
||||
self.level = level
|
||||
self.module = module
|
||||
path = module.path
|
||||
# TODO abspath
|
||||
self.file_path = os.path.dirname(path) if path is not None else None
|
||||
try:
|
||||
self.file_path = module.py__file__()
|
||||
except AttributeError:
|
||||
# Can be None for certain compiled modules like 'builtins'.
|
||||
self.file_path = None
|
||||
|
||||
if level:
|
||||
base = module.py__package__().split('.')
|
||||
@@ -235,15 +237,13 @@ class _Importer(object):
|
||||
else:
|
||||
_add_error(self._evaluator, import_path[-1])
|
||||
import_path = []
|
||||
|
||||
# TODO add import error.
|
||||
debug.warning('Attempted relative import beyond top-level package.')
|
||||
# TODO add import error.
|
||||
debug.warning('Attempted relative import beyond top-level package.')
|
||||
else:
|
||||
# Here we basically rewrite the level to 0.
|
||||
import_path = tuple(base) + import_path
|
||||
self.import_path = import_path
|
||||
|
||||
|
||||
@property
|
||||
def str_import_path(self):
|
||||
"""Returns the import path as pure strings instead of `Name`."""
|
||||
@@ -258,31 +258,20 @@ class _Importer(object):
|
||||
@memoize_default()
|
||||
def sys_path_with_modifications(self):
|
||||
in_path = []
|
||||
sys_path_mod = list(sys_path_with_modifications(self._evaluator, self.module))
|
||||
sys_path_mod = list(sys_path.sys_path_with_modifications(self._evaluator, self.module))
|
||||
if self.file_path is not None:
|
||||
# If you edit e.g. gunicorn, there will be imports like this:
|
||||
# `from gunicorn import something`. But gunicorn is not in the
|
||||
# sys.path. Therefore look if gunicorn is a parent directory, #56.
|
||||
if self.import_path: # TODO is this check really needed?
|
||||
parts = self.file_path.split(os.path.sep)
|
||||
for i, p in enumerate(parts):
|
||||
if p == unicode(self.import_path[0]):
|
||||
new = os.path.sep.join(parts[:i])
|
||||
in_path.append(new)
|
||||
for path in sys_path.traverse_parents(self.file_path):
|
||||
if os.path.basename(path) == self.str_import_path[0]:
|
||||
in_path.append(os.path.dirname(path))
|
||||
|
||||
if not self.module.has_explicit_absolute_import:
|
||||
# If the module explicitly asks for absolute imports,
|
||||
# there's probably a bogus local one.
|
||||
sys_path_mod.insert(0, self.file_path)
|
||||
|
||||
# First the sys path is searched normally and if that doesn't
|
||||
# succeed, try to search the parent directories, because sometimes
|
||||
# Jedi doesn't recognize sys.path modifications (like py.test
|
||||
# stuff).
|
||||
old_path, temp_path = self.file_path, os.path.dirname(self.file_path)
|
||||
while old_path != temp_path:
|
||||
sys_path_mod.append(temp_path)
|
||||
old_path, temp_path = temp_path, os.path.dirname(temp_path)
|
||||
# Since we know nothing about the call location of the sys.path,
|
||||
# it's a possibility that the current directory is the origin of
|
||||
# the Python execution.
|
||||
sys_path_mod.insert(0, os.path.dirname(self.file_path))
|
||||
|
||||
return in_path + sys_path_mod
|
||||
|
||||
|
||||
@@ -760,6 +760,12 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
||||
return name
|
||||
|
||||
def py__file__(self):
|
||||
"""
|
||||
In contrast to Python's __file__ can be None.
|
||||
"""
|
||||
if self._module.path is None:
|
||||
return None
|
||||
|
||||
return os.path.abspath(self._module.path)
|
||||
|
||||
def py__package__(self):
|
||||
|
||||
@@ -188,7 +188,7 @@ def _get_paths_from_buildout_script(evaluator, buildout_script):
|
||||
yield path
|
||||
|
||||
|
||||
def _traverse_parents(path):
|
||||
def traverse_parents(path):
|
||||
while True:
|
||||
new = os.path.dirname(path)
|
||||
if new == path:
|
||||
@@ -198,7 +198,7 @@ def _traverse_parents(path):
|
||||
|
||||
|
||||
def _get_parent_dir_with_file(path, filename):
|
||||
for parent in _traverse_parents(path):
|
||||
for parent in traverse_parents(path):
|
||||
if os.path.isfile(os.path.join(parent, filename)):
|
||||
return parent
|
||||
return None
|
||||
@@ -208,7 +208,7 @@ def _detect_django_path(module_path):
|
||||
""" Detects the path of the very well known Django library (if used) """
|
||||
result = []
|
||||
|
||||
for parent in _traverse_parents(module_path):
|
||||
for parent in traverse_parents(module_path):
|
||||
with common.ignored(IOError):
|
||||
with open(parent + os.path.sep + 'manage.py'):
|
||||
debug.dbg('Found django path: %s', module_path)
|
||||
|
||||
0
test/test_evaluate/not_in_sys_path/pkg/__init__.py
Normal file
0
test/test_evaluate/not_in_sys_path/pkg/__init__.py
Normal file
@@ -1,6 +1,6 @@
|
||||
import not_in_sys_path
|
||||
import not_in_sys_path_package
|
||||
from not_in_sys_path_package import module
|
||||
from not_in_sys_path import not_in_sys_path
|
||||
from not_in_sys_path import not_in_sys_path_package
|
||||
from not_in_sys_path.not_in_sys_path_package import module
|
||||
|
||||
not_in_sys_path.value
|
||||
not_in_sys_path_package.value
|
||||
|
||||
Reference in New Issue
Block a user