forked from VimPlug/jedi
Fix implicit namespace autocompletion. Resolves: #959
This commit is contained in:
@@ -161,6 +161,51 @@ if the module is contained in a package.
|
||||
"""
|
||||
|
||||
|
||||
def _iter_modules(paths, prefix=''):
|
||||
# Copy of pkgutil.iter_modules adapted to work with namespaces
|
||||
for path in paths:
|
||||
importer = pkgutil.get_importer(path)
|
||||
|
||||
if importer.path is None or not os.path.isdir(importer.path):
|
||||
return
|
||||
|
||||
yielded = {}
|
||||
import inspect
|
||||
try:
|
||||
filenames = os.listdir(importer.path)
|
||||
except OSError:
|
||||
# ignore unreadable directories like import does
|
||||
filenames = []
|
||||
filenames.sort() # handle packages before same-named modules
|
||||
|
||||
for fn in filenames:
|
||||
# Avoid traversing special directories
|
||||
if fn.startswith(('__', '.')):
|
||||
continue
|
||||
|
||||
modname = inspect.getmodulename(fn)
|
||||
if modname in yielded:
|
||||
continue
|
||||
|
||||
path = os.path.join(importer.path, fn)
|
||||
ispkg = False
|
||||
|
||||
if not modname and os.path.isdir(path) and '.' not in fn:
|
||||
modname = fn
|
||||
try:
|
||||
dircontents = os.listdir(path)
|
||||
except OSError:
|
||||
# ignore unreadable directories like import does
|
||||
dircontents = []
|
||||
ispkg = True
|
||||
|
||||
if modname and '.' not in modname:
|
||||
yielded[modname] = 1
|
||||
yield importer, prefix + modname, ispkg
|
||||
|
||||
iter_modules = _iter_modules if py_version >= 34 else pkgutil.iter_modules
|
||||
|
||||
|
||||
class ImplicitNSInfo(object):
|
||||
"""Stores information returned from an implicit namespace spec"""
|
||||
def __init__(self, name, paths):
|
||||
|
||||
@@ -5,7 +5,7 @@ import os
|
||||
|
||||
from parso import python_bytes_to_unicode
|
||||
|
||||
from jedi._compatibility import use_metaclass
|
||||
from jedi._compatibility import use_metaclass, iter_modules
|
||||
from jedi.evaluate.cache import CachedMetaClass, evaluator_method_cache
|
||||
from jedi.evaluate.filters import GlobalNameFilter, ContextNameMixin, \
|
||||
AbstractNameDefinition, ParserTreeFilter, DictFilter
|
||||
@@ -188,7 +188,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, TreeContext)):
|
||||
path = self._path
|
||||
names = {}
|
||||
if path is not None and path.endswith(os.path.sep + '__init__.py'):
|
||||
mods = pkgutil.iter_modules([os.path.dirname(path)])
|
||||
mods = iter_modules([os.path.dirname(path)])
|
||||
for module_loader, name, is_pkg in mods:
|
||||
# It's obviously a relative import to the current module.
|
||||
names[name] = SubModuleName(self, name)
|
||||
|
||||
@@ -21,7 +21,7 @@ from parso.tree import search_ancestor
|
||||
from parso.cache import parser_cache
|
||||
from parso import python_bytes_to_unicode
|
||||
|
||||
from jedi._compatibility import find_module, unicode, ImplicitNSInfo
|
||||
from jedi._compatibility import find_module, unicode, ImplicitNSInfo, iter_modules
|
||||
from jedi import debug
|
||||
from jedi import settings
|
||||
from jedi.evaluate import sys_path
|
||||
@@ -401,7 +401,6 @@ class Importer(object):
|
||||
Get the names of all modules in the search_path. This means file names
|
||||
and not names defined in the files.
|
||||
"""
|
||||
|
||||
names = []
|
||||
# add builtin module names
|
||||
if search_path is None and in_module is None:
|
||||
@@ -409,7 +408,7 @@ class Importer(object):
|
||||
|
||||
if search_path is None:
|
||||
search_path = self.sys_path_with_modifications()
|
||||
for module_loader, name, is_pkg in pkgutil.iter_modules(search_path):
|
||||
for module_loader, name, is_pkg in iter_modules(search_path):
|
||||
names.append(self._generate_name(name, in_module=in_module))
|
||||
return names
|
||||
|
||||
@@ -448,7 +447,7 @@ class Importer(object):
|
||||
# implicit namespace packages
|
||||
elif isinstance(context, ImplicitNamespaceContext):
|
||||
paths = context.paths
|
||||
names += self._get_module_names(paths)
|
||||
names += self._get_module_names(paths, in_module=context)
|
||||
|
||||
if only_modules:
|
||||
# In the case of an import like `from x.` we don't need to
|
||||
|
||||
Reference in New Issue
Block a user