def considerImplicitImports(self, module, signal_change): """Provide additional modules to import implicitly when encountering the module. Notes: Better do not overload this method. The standard plugin 'ImplicitImports.py' already contains MANY of these. If you do have a new candidate, consider a PR to get it included there. Args: module: the module object signal_change: bool Returns: None """ from nuitka.importing.Importing import getModuleNameAndKindFromFilename for full_name in self.getImplicitImports(module): if type(full_name) in (tuple, list): raise NuitkaPluginError( "Plugin %s needs to be change to only return modules names, not %r" % (self, full_name)) full_name = ModuleName(full_name) try: module_filename = self.locateModule(importing=module, module_name=full_name) except Exception: self.warning("Problem locating '%s' implicit imports '%s'." % (module.getFullName(), full_name)) raise if module_filename is None: if Options.isShowInclusion(): self.info( "Implicit module '%s' suggested by '%s' not found." % (full_name, module.getFullName())) continue _module_name2, module_kind = getModuleNameAndKindFromFilename( module_filename) # TODO: This should get back to plug-ins, they should be allowed to # preempt or override the decision. decision, reason = self.decideRecursion( module_filename=module_filename, module_name=full_name, module_kind=module_kind, ) if decision: self.recurseTo( module_package=full_name.getPackageName(), module_filename=module_filename, module_kind=module_kind, reason=reason, signal_change=signal_change, )
def considerImplicitImports(self, module, signal_change): """ Provide additional modules to import implicitly when encountering the module. Notes: Better do not overload this method. The standard plugin 'ImplicitImports.py' already contains MANY of these. If you do have a new candidate, consider a PR to get it included there. Args: module: the module object signal_change: bool Returns: None """ from nuitka.importing.Importing import getModuleNameAndKindFromFilename for item in self.getImplicitImports(module): # TODO: Temporary, until all plugins are caught up, turn into an error later. if type(item) in (tuple, list): full_name, _required = item else: full_name = item full_name = ModuleName(full_name) module_filename = self.locateModule(importing=module, module_name=full_name) if module_filename is None: if Options.isShowInclusion(): self.info( "Implicit module '%s' suggested by '%s' not found." % (full_name, module.getFullName())) continue _module_name2, module_kind = getModuleNameAndKindFromFilename( module_filename) # TODO: This should get back to plug-ins, they should be allowed to # preempt or override the decision. decision, reason = self.decideRecursion( module_filename=module_filename, module_name=full_name, module_kind=module_kind, ) if decision: self.recurseTo( module_package=full_name.getPackageName(), module_filename=module_filename, module_kind=module_kind, reason=reason, signal_change=signal_change, )
def considerImplicitImports(self, module, signal_change): """ Provide additional modules to import implicitly when encountering the module. Notes: Better do not overload this method. The standard plugin 'ImplicitImports.py' already contains MANY of these. If you do have a new candidate, consider a PR to get it included there. Args: module: the module object signal_change: bool Returns: None """ from nuitka.importing.Importing import getModuleNameAndKindFromFilename for full_name, required in self.getImplicitImports(module): full_name = ModuleName(full_name) module_filename = self.locateModule( importing=module, module_name=full_name, warn=required ) if module_filename is None: if required: sys.exit( "Error, implicit module '%s' expected by '%s' not found." % (full_name, module.getFullName()) ) else: continue _module_name2, module_kind = getModuleNameAndKindFromFilename( module_filename ) # TODO: This should get back to plug-ins, they should be allowed to # preempt or override the decision. decision, reason = self.decideRecursion( module_filename=module_filename, module_name=full_name, module_kind=module_kind, ) if decision: self.recurseTo( module_package=full_name.getPackageName(), module_filename=module_filename, module_kind=module_kind, reason=reason, signal_change=signal_change, )
def _attemptRecursion(self, trace_collection, 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 module_package, self.module_filename, self.finding = findModule( importing=self, module_name=ModuleName(module_name), parent_package=parent_package, level=level, warn=True, ) if self.module_filename is not None: imported_module = self._consider( trace_collection=trace_collection, module_filename=self.module_filename, module_package=module_package, ) if imported_module is not None: self.imported_module_desc = ( imported_module.getFullName(), imported_module.getFilename(), ) 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 import_list and imported_module.isCompiledPythonPackage(): for import_item in import_list: if import_item == "*": continue module_package, module_filename, _finding = findModule( importing=self, module_name=ModuleName(import_item), parent_package=imported_module.getFullName(), level=-1, # Relative import, so child is used. warn=False, ) if module_filename is not None: sub_imported_module = self._consider( trace_collection=trace_collection, module_filename=module_filename, module_package=module_package, ) if sub_imported_module is not None: self.import_list_modules_desc.append(( sub_imported_module.getFullName(), sub_imported_module.getFilename(), )) else: module_name = ModuleName(module_name) while True: module_name = module_name.getPackageName() if module_name is None: break module_package, module_filename, _finding = findModule( importing=self, module_name=module_name, parent_package=parent_package, level=level, warn=True, ) if module_filename is not None: package_module = self._consider( trace_collection=trace_collection, module_filename=module_filename, module_package=module_package, ) if package_module is not None: if self.package_modules_desc is None: self.package_modules_desc = [] self.package_modules_desc.append( (package_module.getFullName(), package_module.getFilename()))
def findModule(importing, module_name, parent_package, level, warn): """Find a module with given package name as parent. The package name can be None of course. Level is the same as with "__import__" built-in. Warnings are optional. Returns: Returns a triple of package name the module is in, filename of it, which can be a directory for packages, and the location method used. """ # We have many branches here, because there are a lot of cases to try. # pylint: disable=too-many-branches assert type(module_name) is ModuleName, module_name if _debug_module_finding: print("findModule: Enter to search %r in package %r level %s." % (module_name, parent_package, level)) # Do not allow star imports to get here. We just won't find modules with # that name, but it would be wasteful. assert module_name != "*" tried_names = [] if level > 1: # TODO: Should give a warning and return not found if the levels # exceed the package name. if parent_package is not None: # TODO: This should be done with the API instead. parent_package = ModuleName(".".join( parent_package.asString().split(".")[:-level + 1])) if parent_package == "": parent_package = None else: return None, None, "not-found" # Try relative imports first if we have a parent package. if level != 0 and parent_package is not None: if module_name: full_name = ModuleName(parent_package + "." + module_name) else: full_name = ModuleName(parent_package) full_name = normalizePackageName(full_name) tried_names.append(full_name) try: module_filename = _findModule(module_name=full_name) except ImportError: # For relative import, that is OK, we will still try absolute. pass else: if _debug_module_finding: print( "findModule: Relative imported module '%s' as '%s' in filename '%s':" % (module_name, full_name, module_filename)) return full_name.getPackageName(), module_filename, "relative" if level <= 1 and module_name != "": module_name = normalizePackageName(module_name) tried_names.append(module_name) package_name = module_name.getPackageName() # Built-in module names must not be searched any further. if module_name in sys.builtin_module_names: if _debug_module_finding: print( "findModule: Absolute imported module '%s' in as built-in':" % (module_name, )) return package_name, None, "built-in" try: module_filename = _findModule(module_name=module_name) except ImportError: # For relative import, that is OK, we will still try absolute. pass else: if _debug_module_finding: print( "findModule: Found absolute imported module '%s' in filename '%s':" % (module_name, module_filename)) return package_name, module_filename, "absolute" if warn: warnAbout( importing=importing, module_name=module_name, parent_package=parent_package, tried_names=tried_names, level=level, ) return None, None, "not-found"
def findModule(module_name, parent_package, level): """Find a module with given package name as parent. The package name can be None of course. Level is the same as with "__import__" built-in. Warnings are optional. Returns: Returns a triple of package name the module is in, filename of it, which can be a directory for packages, and the location method used. """ # We have many branches here, because there are a lot of cases to try. # pylint: disable=too-many-branches,too-many-return-statements assert type(module_name) is ModuleName, module_name if _debug_module_finding: my_print( "findModule: Enter to search %r in package %r level %s." % (module_name, parent_package, level) ) # Do not allow star imports to get here. We just won't find modules with # that name, but it would be wasteful. assert module_name != "*" if level > 1: # TODO: Should give a warning and return not found if the levels # exceed the package name. if parent_package is not None: parent_package = parent_package.getRelativePackageName(level) else: return None, None, "not-found" # Try relative imports first if we have a parent package. if level != 0 and parent_package is not None: if module_name: full_name = ModuleName(parent_package + "." + module_name) else: full_name = ModuleName(parent_package) full_name = normalizePackageName(full_name) preloaded_path = getPreloadedPackagePath(module_name) if preloaded_path is not None: for module_filename in preloaded_path: if os.path.exists(module_filename): break else: module_filename = None return full_name.getPackageName(), module_filename, "pth" try: module_filename = _findModule(module_name=full_name) except ImportError: # For relative import, that is OK, we will still try absolute. pass else: if _debug_module_finding: my_print( "findModule: Relative imported module '%s' as '%s' in filename '%s':" % (module_name, full_name, module_filename) ) return full_name.getPackageName(), module_filename, "relative" if level < 1 and module_name != "": module_name = normalizePackageName(module_name) package_name = module_name.getPackageName() # Built-in module names must not be searched any further. if module_name in sys.builtin_module_names: if _debug_module_finding: my_print( "findModule: Absolute imported module '%s' in as built-in':" % (module_name,) ) return package_name, None, "built-in" # Frozen module names are similar to built-in, but there is no list of # them, therefore check loader name. Not useful at this time # to make a difference with built-in. if python_version >= 0x300 and module_name in sys.modules: loader = getattr(sys.modules[module_name], "__loader__", None) if ( loader is not None and getattr(loader, "__name__", "") == "FrozenImporter" ): if _debug_module_finding: my_print( "findModule: Absolute imported module '%s' in as frozen':" % (module_name,) ) return package_name, None, "built-in" preloaded_path = getPreloadedPackagePath(module_name) if preloaded_path is not None: for module_filename in preloaded_path: if os.path.exists(module_filename): break else: module_filename = None return package_name, module_filename, "pth" try: module_filename = _findModule(module_name=module_name) except ImportError: # For relative import, that is OK, we will still try absolute. pass else: if _debug_module_finding: my_print( "findModule: Found absolute imported module '%s' in filename '%s':" % (module_name, module_filename) ) return package_name, module_filename, "absolute" return None, None, "not-found"