mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 22:44:27 +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:
|
if eval_stmt is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
module = self._parser.module()
|
module = self._evaluator.wrap(self._parser.module())
|
||||||
names, level, _, _ = helpers.check_error_statements(module, self._pos)
|
names, level, _, _ = helpers.check_error_statements(module, self._pos)
|
||||||
if names:
|
if names:
|
||||||
names = [str(n) for n in names]
|
names = [str(n) for n in names]
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ class CompiledObject(Base):
|
|||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
return bool(self.obj)
|
return bool(self.obj)
|
||||||
|
|
||||||
|
def py__file__(self):
|
||||||
|
return self.obj.__file__
|
||||||
|
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return inspect.isclass(self.obj)
|
return inspect.isclass(self.obj)
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from jedi import debug
|
|||||||
from jedi import cache
|
from jedi import cache
|
||||||
from jedi.parser import fast
|
from jedi.parser import fast
|
||||||
from jedi.parser import tree as pr
|
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.evaluate import helpers
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.common import source_to_unicode
|
from jedi.common import source_to_unicode
|
||||||
@@ -213,9 +213,11 @@ class _Importer(object):
|
|||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self.level = level
|
self.level = level
|
||||||
self.module = module
|
self.module = module
|
||||||
path = module.path
|
try:
|
||||||
# TODO abspath
|
self.file_path = module.py__file__()
|
||||||
self.file_path = os.path.dirname(path) if path is not None else None
|
except AttributeError:
|
||||||
|
# Can be None for certain compiled modules like 'builtins'.
|
||||||
|
self.file_path = None
|
||||||
|
|
||||||
if level:
|
if level:
|
||||||
base = module.py__package__().split('.')
|
base = module.py__package__().split('.')
|
||||||
@@ -235,7 +237,6 @@ class _Importer(object):
|
|||||||
else:
|
else:
|
||||||
_add_error(self._evaluator, import_path[-1])
|
_add_error(self._evaluator, import_path[-1])
|
||||||
import_path = []
|
import_path = []
|
||||||
|
|
||||||
# TODO add import error.
|
# TODO add import error.
|
||||||
debug.warning('Attempted relative import beyond top-level package.')
|
debug.warning('Attempted relative import beyond top-level package.')
|
||||||
else:
|
else:
|
||||||
@@ -243,7 +244,6 @@ class _Importer(object):
|
|||||||
import_path = tuple(base) + import_path
|
import_path = tuple(base) + import_path
|
||||||
self.import_path = import_path
|
self.import_path = import_path
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def str_import_path(self):
|
def str_import_path(self):
|
||||||
"""Returns the import path as pure strings instead of `Name`."""
|
"""Returns the import path as pure strings instead of `Name`."""
|
||||||
@@ -258,31 +258,20 @@ class _Importer(object):
|
|||||||
@memoize_default()
|
@memoize_default()
|
||||||
def sys_path_with_modifications(self):
|
def sys_path_with_modifications(self):
|
||||||
in_path = []
|
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 self.file_path is not None:
|
||||||
# If you edit e.g. gunicorn, there will be imports like this:
|
# If you edit e.g. gunicorn, there will be imports like this:
|
||||||
# `from gunicorn import something`. But gunicorn is not in the
|
# `from gunicorn import something`. But gunicorn is not in the
|
||||||
# sys.path. Therefore look if gunicorn is a parent directory, #56.
|
# sys.path. Therefore look if gunicorn is a parent directory, #56.
|
||||||
if self.import_path: # TODO is this check really needed?
|
if self.import_path: # TODO is this check really needed?
|
||||||
parts = self.file_path.split(os.path.sep)
|
for path in sys_path.traverse_parents(self.file_path):
|
||||||
for i, p in enumerate(parts):
|
if os.path.basename(path) == self.str_import_path[0]:
|
||||||
if p == unicode(self.import_path[0]):
|
in_path.append(os.path.dirname(path))
|
||||||
new = os.path.sep.join(parts[:i])
|
|
||||||
in_path.append(new)
|
|
||||||
|
|
||||||
if not self.module.has_explicit_absolute_import:
|
# Since we know nothing about the call location of the sys.path,
|
||||||
# If the module explicitly asks for absolute imports,
|
# it's a possibility that the current directory is the origin of
|
||||||
# there's probably a bogus local one.
|
# the Python execution.
|
||||||
sys_path_mod.insert(0, self.file_path)
|
sys_path_mod.insert(0, os.path.dirname(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)
|
|
||||||
|
|
||||||
return in_path + sys_path_mod
|
return in_path + sys_path_mod
|
||||||
|
|
||||||
|
|||||||
@@ -760,6 +760,12 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
def py__file__(self):
|
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)
|
return os.path.abspath(self._module.path)
|
||||||
|
|
||||||
def py__package__(self):
|
def py__package__(self):
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ def _get_paths_from_buildout_script(evaluator, buildout_script):
|
|||||||
yield path
|
yield path
|
||||||
|
|
||||||
|
|
||||||
def _traverse_parents(path):
|
def traverse_parents(path):
|
||||||
while True:
|
while True:
|
||||||
new = os.path.dirname(path)
|
new = os.path.dirname(path)
|
||||||
if new == path:
|
if new == path:
|
||||||
@@ -198,7 +198,7 @@ def _traverse_parents(path):
|
|||||||
|
|
||||||
|
|
||||||
def _get_parent_dir_with_file(path, filename):
|
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)):
|
if os.path.isfile(os.path.join(parent, filename)):
|
||||||
return parent
|
return parent
|
||||||
return None
|
return None
|
||||||
@@ -208,7 +208,7 @@ def _detect_django_path(module_path):
|
|||||||
""" Detects the path of the very well known Django library (if used) """
|
""" Detects the path of the very well known Django library (if used) """
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
for parent in _traverse_parents(module_path):
|
for parent in traverse_parents(module_path):
|
||||||
with common.ignored(IOError):
|
with common.ignored(IOError):
|
||||||
with open(parent + os.path.sep + 'manage.py'):
|
with open(parent + os.path.sep + 'manage.py'):
|
||||||
debug.dbg('Found django path: %s', module_path)
|
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
|
from not_in_sys_path import not_in_sys_path
|
||||||
import not_in_sys_path_package
|
from not_in_sys_path import not_in_sys_path_package
|
||||||
from not_in_sys_path_package import module
|
from not_in_sys_path.not_in_sys_path_package import module
|
||||||
|
|
||||||
not_in_sys_path.value
|
not_in_sys_path.value
|
||||||
not_in_sys_path_package.value
|
not_in_sys_path_package.value
|
||||||
|
|||||||
Reference in New Issue
Block a user