1
0
forked from VimPlug/jedi

make a translation from file system paths to dotted paths possible

This commit is contained in:
Dave Halter
2014-06-25 16:33:25 +02:00
parent 718df569ea
commit 01869e4100

View File

@@ -12,6 +12,7 @@ This module also supports import autocompletion, which means to complete
statements like ``from datetim`` (curser at the end would return ``datetime``). statements like ``from datetim`` (curser at the end would return ``datetime``).
""" """
import os import os
import re
import pkgutil import pkgutil
import sys import sys
from itertools import chain from itertools import chain
@@ -22,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 representation as pr from jedi.parser import representation as pr
from jedi.evaluate import sys_path from jedi.evaluate.sys_path import get_sys_path, sys_path_with_modifications
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
@@ -105,7 +106,7 @@ class ImportWrapper(pr.Base):
if self._is_relative_import(): if self._is_relative_import():
rel_path = self._importer.get_relative_path() + '/__init__.py' rel_path = self._importer.get_relative_path() + '/__init__.py'
if os.path.exists(rel_path): if os.path.exists(rel_path):
m = load_module(rel_path) m = _load_module(rel_path)
names += m.get_defined_names() names += m.get_defined_names()
else: else:
if on_import_stmt and isinstance(scope, pr.Module) \ if on_import_stmt and isinstance(scope, pr.Module) \
@@ -331,7 +332,7 @@ class _Importer(object):
new = os.path.sep.join(parts[:i]) new = os.path.sep.join(parts[:i])
in_path.append(new) in_path.append(new)
return in_path + sys_path.sys_path_with_modifications(self._evaluator, self.module) return in_path + sys_path_with_modifications(self._evaluator, self.module)
def follow(self, evaluator): def follow(self, evaluator):
scope, rest = self.follow_file_system() scope, rest = self.follow_file_system()
@@ -358,7 +359,7 @@ class _Importer(object):
sys_path_mod.append(temp_path) sys_path_mod.append(temp_path)
old_path, temp_path = temp_path, os.path.dirname(temp_path) old_path, temp_path = temp_path, os.path.dirname(temp_path)
else: else:
sys_path_mod = list(sys_path.get_sys_path()) sys_path_mod = list(get_sys_path())
return self._follow_sys_path(sys_path_mod) return self._follow_sys_path(sys_path_mod)
@@ -461,9 +462,9 @@ class _Importer(object):
else: else:
source = current_namespace[0].read() source = current_namespace[0].read()
current_namespace[0].close() current_namespace[0].close()
return load_module(path, source), rest return _load_module(path, source, sys_path=sys_path), rest
else: else:
return load_module(name=path), rest return _load_module(name=path, sys_path=sys_path), rest
def follow_imports(evaluator, scopes): def follow_imports(evaluator, scopes):
@@ -508,7 +509,7 @@ def remove_star_imports(evaluator, scope, ignored_modules=()):
return set(modules) return set(modules)
def load_module(path=None, source=None, name=None): def _load_module(path=None, source=None, name=None, sys_path=None):
def load(source): def load(source):
if path is not None and path.endswith('.py'): if path is not None and path.endswith('.py'):
if source is None: if source is None:
@@ -525,6 +526,26 @@ def load_module(path=None, source=None, name=None):
return load(source) if cached is None else cached.module return load(source) if cached is None else cached.module
def _reverse_fs_path(fs_path, sys_path=None):
"""
Changes `/usr/lib/python3.4/email/utils.py` to `email.utils`. I.e.
compares the path with sys.path and then returns the dotted_path. If the
path is not in the sys.path, just returns None.
"""
sep = os.path.sep
shortest = None
sys_path = get_sys_path()
for s in sys_path:
if fs_path.startswith(s):
path = fs_path[len(s):].strip(sep)
path = re.sub('\.[^%s]*|%s__init__.py$' % (sep, sep), '', path)
dotted = '.'.join(path.split(sep))
# At this point dotted could be both `lib-dynload.datetime` and
# `datetime`. The shorter one is typically the module we want.
if shortest is None or len(shortest) > len(dotted):
shortest = dotted
return shortest
def get_modules_containing_name(mods, name): def get_modules_containing_name(mods, name):
""" """
Search a name in the directories of modules. Search a name in the directories of modules.
@@ -542,7 +563,7 @@ def get_modules_containing_name(mods, name):
with open(path, 'rb') as f: with open(path, 'rb') as f:
source = source_to_unicode(f.read()) source = source_to_unicode(f.read())
if name in source: if name in source:
return load_module(path, source) return _load_module(path, source)
# skip non python modules # skip non python modules
mods = set(m for m in mods if not isinstance(m, compiled.CompiledObject)) mods = set(m for m in mods if not isinstance(m, compiled.CompiledObject))