1
0
forked from VimPlug/jedi

Some import fixes.

This commit is contained in:
Dave Halter
2016-11-12 01:01:47 +01:00
parent 052f6bf9e7
commit e4ea9bb630
2 changed files with 33 additions and 32 deletions

View File

@@ -18,7 +18,6 @@ import sys
from itertools import chain from itertools import chain
from jedi._compatibility import find_module, unicode from jedi._compatibility import find_module, unicode
from jedi import common
from jedi import debug from jedi import debug
from jedi.parser import fast from jedi.parser import fast
from jedi.parser import tree from jedi.parser import tree
@@ -26,7 +25,7 @@ from jedi.parser.utils import save_parser, load_parser, parser_cache
from jedi.evaluate import sys_path 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, unite
from jedi.evaluate import compiled from jedi.evaluate import compiled
from jedi.evaluate import analysis from jedi.evaluate import analysis
@@ -62,16 +61,15 @@ class ImportWrapper(object):
self._context = context self._context = context
self._name = name self._name = name
self._import = name.get_parent_until(tree.Import)
self.import_path = self._import.path_for_name(name)
# TODO move this whole thing to a function # TODO move this whole thing to a function
def follow(self, is_goto=False): def follow(self, is_goto=False):
module = self._import.get_parent_until() module_context = self._context.get_root_context()
import_path = self._import.path_for_name(self._name) import_node = self._name.get_parent_until(tree.Import)
import_path = import_node.path_for_name(self._name)
from_import_name = None from_import_name = None
evaluator = self._context.evaluator
try: try:
from_names = self._import.get_from_names() from_names = import_node.get_from_names()
except AttributeError: except AttributeError:
# Is an import_name # Is an import_name
pass pass
@@ -82,24 +80,26 @@ class ImportWrapper(object):
from_import_name = import_path[-1] from_import_name = import_path[-1]
import_path = from_names import_path = from_names
importer = Importer(self._context.evaluator, tuple(import_path), importer = Importer(evaluator, tuple(import_path),
module, self._import.level) module_context, import_node.level)
# TODO This is terrible, why different Importer instances?
types = importer.follow() types = importer.follow()
#if self._import.is_nested() and not self.nested_resolve: #if import_node.is_nested() and not self.nested_resolve:
# scopes = [NestedImportModule(module, self._import)] # scopes = [NestedImportModule(module, import_node)]
if from_import_name is not None: if from_import_name is not None:
types = set(chain.from_iterable( types = unite(
self.evaluator.find_types(t, unicode(from_import_name), evaluator.find_types(t, unicode(from_import_name),
is_goto=is_goto) is_goto=is_goto)
for t in types)) for t in types
)
if not types: if not types:
path = import_path + [from_import_name] path = import_path + [from_import_name]
importer = Importer(self.evaluator, tuple(path), importer = Importer(evaluator, tuple(path),
module, self._import.level) module_context, import_node.level)
types = importer.follow() types = importer.follow()
# goto only accepts `Name` # goto only accepts `Name`
if is_goto: if is_goto:
@@ -164,7 +164,7 @@ def get_init_path(directory_path):
class Importer(object): class Importer(object):
def __init__(self, evaluator, import_path, module, level=0): def __init__(self, evaluator, import_path, module_context, level=0):
""" """
An implementation similar to ``__import__``. Use `follow` An implementation similar to ``__import__``. Use `follow`
to actually follow the imports. to actually follow the imports.
@@ -180,19 +180,19 @@ class Importer(object):
debug.speed('import %s' % (import_path,)) debug.speed('import %s' % (import_path,))
self._evaluator = evaluator self._evaluator = evaluator
self.level = level self.level = level
self.module = module self.module_context = module_context
try: try:
self.file_path = module.py__file__() self.file_path = module_context.py__file__()
except AttributeError: except AttributeError:
# Can be None for certain compiled modules like 'builtins'. # Can be None for certain compiled modules like 'builtins'.
self.file_path = None self.file_path = None
if level: if level:
base = module.py__package__().split('.') base = module_context.py__package__().split('.')
if base == ['']: if base == ['']:
base = [] base = []
if level > len(base): if level > len(base):
path = module.py__file__() path = module_context.py__file__()
if path is not None: if path is not None:
import_path = list(import_path) import_path = list(import_path)
for i in range(level): for i in range(level):
@@ -220,7 +220,10 @@ class Importer(object):
def sys_path_with_modifications(self): def sys_path_with_modifications(self):
in_path = [] in_path = []
sys_path_mod = list(sys_path.sys_path_with_modifications(self._evaluator, self.module)) sys_path_mod = list(sys_path.sys_path_with_modifications(
self._evaluator,
self.module_context
))
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
@@ -285,12 +288,13 @@ class Importer(object):
return self._evaluator.find_types(parent_module, 'path') return self._evaluator.find_types(parent_module, 'path')
try: try:
paths = parent_module.py__path__() method = parent_module.py__path__
except AttributeError: except AttributeError:
# The module is not a package. # The module is not a package.
_add_error(self._evaluator, import_path[-1]) _add_error(self._evaluator, import_path[-1])
return set() return set()
else: else:
paths = method()
debug.dbg('search_module %s in paths %s', module_name, paths) debug.dbg('search_module %s in paths %s', module_name, paths)
for path in paths: for path in paths:
# At the moment we are only using one path. So this is # At the moment we are only using one path. So this is
@@ -349,7 +353,7 @@ class Importer(object):
def _generate_name(self, name): def _generate_name(self, name):
# Create a pseudo import to be able to follow them. # Create a pseudo import to be able to follow them.
name = helpers.FakeName(name) name = helpers.FakeName(name)
imp = helpers.FakeImport(name, parent=self.module) imp = helpers.FakeImport(name, parent=self.module_context)
name.parent = imp name.parent = imp
return name return name
@@ -443,7 +447,7 @@ def _load_module(evaluator, path=None, source=None, sys_path=None, parent_module
else: else:
return compiled.load_module(evaluator, path) return compiled.load_module(evaluator, path)
p = path p = path
p = fast.FastParser(evaluator.grammar, common.source_to_unicode(source), p) p = fast.FastParser(evaluator.grammar, source_to_unicode(source), p)
save_parser(path, p) save_parser(path, p)
return p.module return p.module

View File

@@ -776,7 +776,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper)
origin_scope=origin_scope origin_scope=origin_scope
) )
yield GlobalNameFilter(self, self.module_node) yield GlobalNameFilter(self, self.module_node)
yield DictFilter(self._sub_modules_dict()) #yield DictFilter(self._sub_modules_dict())
yield DictFilter(self._module_attributes_dict()) yield DictFilter(self._module_attributes_dict())
# TODO # TODO
''' '''
@@ -853,10 +853,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper)
return self.py__name__() return self.py__name__()
def _py__path__(self): def _py__path__(self):
if self._parent_module is None: search_path = self.evaluator.sys_path
search_path = self.evaluator.sys_path
else:
search_path = self._parent_module.py__path__()
init_path = self.py__file__() init_path = self.py__file__()
if os.path.basename(init_path) == '__init__.py': if os.path.basename(init_path) == '__init__.py':
with open(init_path, 'rb') as f: with open(init_path, 'rb') as f: