def __init__(self, module_name, source_ref): ExpressionBase.__init__(self, source_ref=source_ref) self.module_name = resolveModuleName(module_name) self.finding = None # If not found, we import the package at least ( self.found_module_name, self.found_module_filename, self.finding, ) = self._attemptFollow()
def computeExpression(self, trace_collection): # Attempt to recurse if not already done. if self.follow_attempted: if self.finding == "not-found": # Importing and not finding, may raise an exception obviously. trace_collection.onExceptionRaiseExit(BaseException) else: # If we know it exists, only RuntimeError shall occur. trace_collection.onExceptionRaiseExit(RuntimeError) # We stay here. return self, None, None module_name = self.subnode_name if module_name.isCompileTimeConstant(): imported_module_name = module_name.getCompileTimeConstant() module_filename = self._attemptFollow( module_name=imported_module_name) self.follow_attempted = True if type(imported_module_name) in (str, unicode): imported_module_name = resolveModuleName(imported_module_name) if self.finding == "absolute" and imported_module_name in hard_modules: if (isStandardLibraryPath(module_filename) or imported_module_name == "pkg_resources"): result = ExpressionImportModuleHard( module_name=imported_module_name, source_ref=self.source_ref) return ( result, "new_expression", "Lowered import of standard library module '%s' to hard import." % imported_module_name.asString(), ) elif shallWarnUnusualCode(): unusual_logger.warning( "%s: Standard library module '%s' used from outside path %r." % ( self.source_ref.getAsString(), imported_module_name.asString(), self.module_filename, )) if self.finding == "built-in": if imported_module_name in hard_modules: result = ExpressionImportModuleHard( module_name=imported_module_name, source_ref=self.source_ref) return ( result, "new_expression", "Lowered import of built-in module '%s' to hard import." % imported_module_name.asString(), ) self.type_shape = tshape_module_builtin self.builtin_module = __import__(imported_module_name) else: # TODO: This doesn't preserve side effects. # Non-strings is going to raise an error. ( new_node, change_tags, message, ) = trace_collection.getCompileTimeComputationResult( node=self, computation=lambda: __import__(module_name. getCompileTimeConstant()), description= "Replaced '__import__' call with non-string module name argument.", ) # Must fail, must not go on when it doesn't. assert change_tags == "new_raise", module_name return new_node, change_tags, message # Importing may raise an exception obviously, unless we know it will # not. if self.finding != "built-in": trace_collection.onExceptionRaiseExit(BaseException) # TODO: May return a module or module variable reference of some sort in # the future with embedded modules. return self, None, None
def _attemptFollow(self, module_name): # Complex stuff, pylint: disable=too-many-branches parent_module = self.getParentModule() parent_package = parent_module.getFullName() if not parent_module.isCompiledPythonPackage(): parent_package = parent_package.getPackageName() level = self.subnode_level if level is None: level = 0 if parent_module.getFutureSpec().isAbsoluteImport( ) else -1 elif not level.isCompileTimeConstant(): return else: level = level.getCompileTimeConstant() # TODO: Catch this as a static error maybe. if type(level) not in (int, long): return None, None module_name, module_filename, self.finding = locateModule( module_name=resolveModuleName(module_name), parent_package=parent_package, level=level, ) if self.finding != "not-found": self.used_modules = [(module_name, module_filename, self.finding, level)] import_list = self.subnode_fromlist if import_list is not None: if import_list.isCompileTimeConstant(): import_list = import_list.getCompileTimeConstant() if type(import_list) not in (tuple, list): import_list = None if (module_filename is not None and import_list and isPackageDir(module_filename)): for import_item in import_list: if import_item == "*": continue ( name_import_module_name, name_import_module_filename, name_import_finding, ) = locateModule( module_name=ModuleName(import_item), parent_package=module_name, level=1, # Relative import ) if name_import_module_filename is not None: self.used_modules.append(( name_import_module_name, name_import_module_filename, name_import_finding, 1, )) return module_filename else: module_name = resolveModuleName(module_name) while True: module_name = module_name.getPackageName() if module_name is None: break module_name_found, module_filename, finding = locateModule( module_name=module_name, parent_package=parent_package, level=level, ) if module_filename is not None: self.used_modules = [(module_name_found, module_filename, finding, level)] return None