Following os.path should be possible again.

This commit is contained in:
Dave Halter
2015-04-22 03:35:18 +02:00
parent dd3edd15f9
commit 29bd59a355
+26 -44
View File
@@ -96,19 +96,11 @@ class ImportWrapper(pr.Base):
importer = get_importer(self._evaluator, tuple(import_path), importer = get_importer(self._evaluator, tuple(import_path),
module, self._import.level) module, self._import.level)
try:
module, rest = importer.follow_file_system()
except ModuleNotFound as e:
analysis.add(self._evaluator, 'import-error', e.name)
return []
if module is None: types, rest = importer.follow_file_system()
# TODO does that really happen? Why?
return []
#if self._import.is_nested() and not self.nested_resolve: #if self._import.is_nested() and not self.nested_resolve:
# scopes = [NestedImportModule(module, self._import)] # scopes = [NestedImportModule(module, self._import)]
types = [module]
if from_import_name is not None: if from_import_name is not None:
types = list(chain.from_iterable( types = list(chain.from_iterable(
@@ -118,11 +110,7 @@ class ImportWrapper(pr.Base):
importer = get_importer(self._evaluator, importer = get_importer(self._evaluator,
tuple(import_path + [from_import_name]), tuple(import_path + [from_import_name]),
module, self._import.level) module, self._import.level)
module, _ = importer.follow_file_system() types, _ = importer.follow_file_system()
if module is None:
types = []
else:
types = [module]
@@ -302,39 +290,17 @@ class _Importer(object):
def follow(self, evaluator): def follow(self, evaluator):
try: try:
scope, rest = self.follow_file_system() scopes, _ = self.follow_file_system()
except ModuleNotFound: except ModuleNotFound:
return [] return []
if scope is None:
return []
if rest:
# follow the rest of the import (not FS -> classes, functions)
return self.follow_rest(scope, rest)
return [scope]
def follow_rest(self, module, rest):
# Either os.path or path length is smaller.
if len(rest) < 2 or len(self.str_import_path) < 4 \
and ('os', 'path') == self.str_import_path[:2] and self.level == 0:
# This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python
# that is being achieved by messing with ``sys.modules`` in
# ``os``.
scopes = [module]
for r in rest:
scopes = list(chain.from_iterable(
self._evaluator.find_types(s, r)
for s in scopes))
return scopes return scopes
else:
return []
@memoize_default(NO_DEFAULT) @memoize_default(NO_DEFAULT)
def follow_file_system(self): def follow_file_system(self):
if not self.import_path: if not self.import_path:
return None, [] return None, []
module = self._do_import(self.import_path, self.sys_path_with_modifications()) modules = self._do_import(self.import_path, self.sys_path_with_modifications())
return module, [] return modules, []
# TODO delete - move! # TODO delete - move!
@@ -413,19 +379,35 @@ class _Importer(object):
import_parts = [str(i) for i in import_path] import_parts = [str(i) for i in import_path]
module_name = '.'.join(import_parts) module_name = '.'.join(import_parts)
try: try:
return self._evaluator.modules[module_name] return [self._evaluator.modules[module_name]]
except KeyError: except KeyError:
pass
try: 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.
base = self._do_import(import_path[:-1], sys_path) bases = self._do_import(import_path[:-1], sys_path)
if not bases:
return []
# We can take the first element, because only the os special
# case yields multiple modules, which is not important for
# further imports.
base = bases[0]
# This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python
# that is being achieved by messing with ``sys.modules`` in
# ``os``.
if [str(i) for i in import_path] == ['os', 'path']:
return self._evaluator.find_types(base, 'path')
try: try:
paths = base.py__path__() paths = base.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 None 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:
@@ -444,7 +426,7 @@ class _Importer(object):
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 None return []
else: else:
source = None source = None
if is_pkg: if is_pkg:
@@ -467,7 +449,7 @@ class _Importer(object):
sys_path, module_name) sys_path, module_name)
self._evaluator.modules[module_name] = module self._evaluator.modules[module_name] = module
return module return [module]
def _generate_name(self, name): def _generate_name(self, name):
return helpers.FakeName(name, parent=self.module) return helpers.FakeName(name, parent=self.module)