forked from VimPlug/jedi
Namespace packages work again. This time the same way as Python does it.
This commit is contained in:
@@ -389,39 +389,46 @@ class _Importer(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
if len(import_path) > 1:
|
||||||
if len(import_path) > 1:
|
# This is a recursive way of importing that works great with
|
||||||
# This is a recursive way of importing that works great with
|
# the module cache.
|
||||||
# the module cache.
|
bases = self._do_import(import_path[:-1], sys_path)
|
||||||
bases = self._do_import(import_path[:-1], sys_path)
|
if not bases:
|
||||||
if not bases:
|
return []
|
||||||
return []
|
# We can take the first element, because only the os special
|
||||||
# We can take the first element, because only the os special
|
# case yields multiple modules, which is not important for
|
||||||
# case yields multiple modules, which is not important for
|
# further imports.
|
||||||
# further imports.
|
base = bases[0]
|
||||||
base = bases[0]
|
|
||||||
|
|
||||||
# This is a huge exception, we follow a nested import
|
# This is a huge exception, we follow a nested import
|
||||||
# ``os.path``, because it's a very important one in Python
|
# ``os.path``, because it's a very important one in Python
|
||||||
# that is being achieved by messing with ``sys.modules`` in
|
# that is being achieved by messing with ``sys.modules`` in
|
||||||
# ``os``.
|
# ``os``.
|
||||||
if [str(i) for i in import_path] == ['os', 'path']:
|
if [str(i) for i in import_path] == ['os', 'path']:
|
||||||
return self._evaluator.find_types(base, 'path')
|
return self._evaluator.find_types(base, 'path')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
paths = base.py__path__()
|
paths = base.py__path__(sys_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 []
|
return []
|
||||||
else:
|
else:
|
||||||
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
|
||||||
# not important to be correct.
|
# not important to be correct.
|
||||||
|
try:
|
||||||
module_file, module_path, is_pkg = \
|
module_file, module_path, is_pkg = \
|
||||||
find_module(import_parts[-1], [path])
|
find_module(import_parts[-1], [path])
|
||||||
else:
|
break
|
||||||
|
except ImportError:
|
||||||
|
module_path = None
|
||||||
|
if module_path is None:
|
||||||
|
_add_error(self._evaluator, import_path[-1])
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
try:
|
||||||
debug.dbg('search_module %s in %s', import_parts[-1], self.file_path)
|
debug.dbg('search_module %s in %s', import_parts[-1], self.file_path)
|
||||||
# Override the sys.path. It works only good that way.
|
# Override the sys.path. It works only good that way.
|
||||||
# Injecting the path directly into `find_module` did not work.
|
# Injecting the path directly into `find_module` did not work.
|
||||||
@@ -431,30 +438,30 @@ class _Importer(object):
|
|||||||
find_module(import_parts[-1])
|
find_module(import_parts[-1])
|
||||||
finally:
|
finally:
|
||||||
sys.path = temp
|
sys.path = temp
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# 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 []
|
return []
|
||||||
else:
|
|
||||||
source = None
|
|
||||||
if is_pkg:
|
|
||||||
# In this case, we don't have a file yet. Search for the
|
|
||||||
# __init__ file.
|
|
||||||
for suffix, _, _ in imp.get_suffixes():
|
|
||||||
path = os.path.join(module_path, '__init__' + suffix)
|
|
||||||
if os.path.exists(path):
|
|
||||||
if suffix == '.py':
|
|
||||||
module_path = path
|
|
||||||
break
|
|
||||||
elif module_file:
|
|
||||||
source = module_file.read()
|
|
||||||
module_file.close()
|
|
||||||
|
|
||||||
if module_file is None and not module_path.endswith('.py'):
|
source = None
|
||||||
module = compiled.load_module(module_path)
|
if is_pkg:
|
||||||
else:
|
# In this case, we don't have a file yet. Search for the
|
||||||
module = _load_module(self._evaluator, module_path, source,
|
# __init__ file.
|
||||||
sys_path, module_name)
|
for suffix, _, _ in imp.get_suffixes():
|
||||||
|
path = os.path.join(module_path, '__init__' + suffix)
|
||||||
|
if os.path.exists(path):
|
||||||
|
if suffix == '.py':
|
||||||
|
module_path = path
|
||||||
|
break
|
||||||
|
elif module_file:
|
||||||
|
source = module_file.read()
|
||||||
|
module_file.close()
|
||||||
|
|
||||||
|
if module_file is None and not module_path.endswith('.py'):
|
||||||
|
module = compiled.load_module(module_path)
|
||||||
|
else:
|
||||||
|
module = _load_module(self._evaluator, module_path, source,
|
||||||
|
sys_path, module_name)
|
||||||
|
|
||||||
self._evaluator.modules[module_name] = module
|
self._evaluator.modules[module_name] = module
|
||||||
return [module]
|
return [module]
|
||||||
|
|||||||
@@ -786,11 +786,34 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
|||||||
@property
|
@property
|
||||||
def py__path__(self):
|
def py__path__(self):
|
||||||
"""
|
"""
|
||||||
|
Not seen here, since it's a property. The callback actually uses a
|
||||||
|
variable, so use it like::
|
||||||
|
|
||||||
|
foo.py__path__(sys_path)
|
||||||
|
|
||||||
In case of a package, this returns Python's __path__ attribute, which
|
In case of a package, this returns Python's __path__ attribute, which
|
||||||
is a list of paths (strings).
|
is a list of paths (strings).
|
||||||
Raises an AttributeError if the module is not a package.
|
Raises an AttributeError if the module is not a package.
|
||||||
"""
|
"""
|
||||||
def return_value():
|
def return_value(search_path):
|
||||||
|
init_path = self.py__file__()
|
||||||
|
if os.path.basename(init_path) == '__init__.py':
|
||||||
|
|
||||||
|
with open(init_path, 'rb') as f:
|
||||||
|
content = common.source_to_unicode(f.read())
|
||||||
|
# these are strings that need to be used for namespace packages,
|
||||||
|
# the first one is ``pkgutil``, the second ``pkg_resources``.
|
||||||
|
options = ('declare_namespace(__name__)', 'extend_path(__path__')
|
||||||
|
if options[0] in content or options[1] in content:
|
||||||
|
# It is a namespace, now try to find the rest of the
|
||||||
|
# modules on sys_path or whatever the search_path is.
|
||||||
|
paths = set()
|
||||||
|
for s in search_path:
|
||||||
|
other = os.path.join(s, unicode(self.name))
|
||||||
|
if os.path.isdir(other):
|
||||||
|
paths.add(other)
|
||||||
|
return list(paths)
|
||||||
|
# Default to this.
|
||||||
return [path]
|
return [path]
|
||||||
|
|
||||||
path = self._get_init_directory()
|
path = self._get_init_directory()
|
||||||
|
|||||||
Reference in New Issue
Block a user