def load_module(self, name, extra_path=None): """Load a Python module that should be useable from Jamfiles. There are generally two types of modules Jamfiles might want to use: - Core Boost.Build. Those are imported using plain names, e.g. 'toolset', so this function checks if we have module named b2.package.module already. - Python modules in the same directory as Jamfile. We don't want to even temporary add Jamfile's directory to sys.path, since then we might get naming conflicts between standard Python modules and those. """ # See if we loaded module of this name already existing = self.loaded_tool_modules_.get(name) if existing: return existing # See if we have a module b2.whatever.<name>, where <name> # is what is passed to this function modules = sys.modules for class_name in modules: parts = class_name.split('.') if name is class_name or parts[0] == "b2" \ and parts[-1] == name.replace("-", "_"): module = modules[class_name] self.loaded_tool_modules_[name] = module return module # Lookup a module in BOOST_BUILD_PATH path = extra_path if not path: path = [] path.extend(self.manager.boost_build_path()) location = None for p in path: l = os.path.join(p, name + ".py") if os.path.exists(l): location = l break if not location: self.manager.errors()("Cannot find module '%s'" % name) mname = name + "__for_jamfile" file = open(location) try: # TODO: this means we'll never make use of .pyc module, # which might be a problem, or not. self.loaded_tool_module_path_[mname] = location module = imp.load_module(mname, file, os.path.basename(location), (".py", "r", imp.PY_SOURCE)) self.loaded_tool_modules_[name] = module return module finally: file.close()
def load_module(self, name, extra_path=None): """Classic Boost.Build 'modules' are in fact global variables. Therefore, try to find an already loaded Python module called 'name' in sys.modules. If the module ist not loaded, find it Boost.Build search path and load it. The new module is not entered in sys.modules. The motivation here is to have disjoint namespace of modules loaded via 'import/using' in Jamfile, and ordinary Python modules. We don't want 'using foo' in Jamfile to load ordinary Python module 'foo' which is going to not work. And we also don't want 'import foo' in regular Python module to accidentally grab module named foo that is internal to Boost.Build and intended to provide interface to Jamfiles.""" existing = self.loaded_tool_modules_.get(name) if existing: return existing modules = sys.modules for class_name in modules: if name is class_name: module = modules[class_name] self.loaded_tool_modules_[name] = module return module path = extra_path if not path: path = [] path.extend(self.manager.boost_build_path()) location = None for p in path: l = os.path.join(p, name + ".py") if os.path.exists(l): location = l break if not location: self.manager.errors()("Cannot find module '%s'" % name) mname = "__build_build_temporary__" file = open(location) try: # TODO: this means we'll never make use of .pyc module, # which might be a problem, or not. module = imp.load_module(mname, file, os.path.basename(location), (".py", "r", imp.PY_SOURCE)) del sys.modules[mname] self.loaded_tool_modules_[name] = module return module finally: file.close()