1import inspect 2import logging 3import imp 4import os.path 5 6 7class IModuleLoader: 8 def __init__(self, **params): 9 self.set_params(**params) 10 11 def set_params(self, **params): 12 raise NotImplementedError 13 14 def load(self, registrant): 15 raise NotImplementedError 16 17 18class FileLoader(IModuleLoader): 19 def __init__(self, **params): 20 IModuleLoader.__init__(self, **params) 21 self.__logger = logging.getLogger("libraries.FileLoader") 22 23 def set_params(self, **params): 24 if "base_path" not in params: 25 return 26 elif "filename" not in params: 27 return 28 29 self.filename = params["filename"] 30 self.base_path = params["base_path"] 31 if self.base_path.endswith("/"): 32 self.base_path = self.base_path[:-1] 33 34 def load(self, registrant): 35 self.module_registrant = registrant 36 37 self._load_py_from_file(os.path.join(self.base_path, self.filename)) 38 39 def _build_id(self, filename, objname): 40 filepath, filename = os.path.split(filename) 41 42 relative_path = os.path.relpath(filepath, self.base_path) 43 identifier = relative_path + "/" + objname 44 if identifier.startswith("./"): 45 identifier = identifier[2:] 46 47 return identifier 48 49 def _load_py_from_file(self, filename): 50 """ 51 Opens "filename", inspects it and calls the registrant 52 """ 53 self.__logger.debug("__load_py_from_file. START, file=%s" % (filename,)) 54 55 dirname, filename = os.path.split(filename) 56 fn = os.path.splitext(filename)[0] 57 exten_file = None 58 module = None 59 60 try: 61 exten_file, filename, description = imp.find_module(fn, [dirname]) 62 module = imp.load_module(fn, exten_file, filename, description) 63 except ImportError as msg: 64 self.__logger.critical( 65 "__load_py_from_file. Filename: %s Exception, msg=%s" % (filename, msg) 66 ) 67 # raise msg 68 pass 69 except SyntaxError as msg: 70 # incorrect python syntax in file 71 self.__logger.critical( 72 "__load_py_from_file. Filename: %s Exception, msg=%s" % (filename, msg) 73 ) 74 # raise msg 75 pass 76 finally: 77 if exten_file: 78 exten_file.close() 79 80 if module is None: 81 return 82 83 for objname in dir(module): 84 obj = getattr(module, objname) 85 self.__logger.debug("__load_py_from_file. inspecting=%s" % (objname,)) 86 if inspect.isclass(obj): 87 if "__PLUGIN_MODULEMAN_MARK" in dir(obj): 88 if self.module_registrant: 89 self.module_registrant.register( 90 self._build_id(filename, objname), obj 91 ) 92 93 self.__logger.debug("__load_py_from_file. END, loaded file=%s" % (filename,)) 94 95 96class DirLoader(FileLoader): 97 def __init__(self, **params): 98 FileLoader.__init__(self, **params) 99 self.__logger = logging.getLogger("libraries.DirLoader") 100 101 def set_params(self, **params): 102 if "base_dir" not in params: 103 return 104 elif "base_path" not in params: 105 return 106 107 self.base_dir = params["base_dir"] 108 self.base_path = params["base_path"] 109 if self.base_path.endswith("/"): 110 self.base_path = self.base_path[:-1] 111 112 def load(self, registrant): 113 self.module_registrant = registrant 114 self.structure = self.__load_all(self.base_dir) 115 116 def _build_id(self, filename, objname): 117 filepath, filename = os.path.split(filename) 118 119 relative_path = os.path.relpath( 120 filepath, os.path.join(self.base_path, self.base_dir) 121 ) 122 identifier = relative_path + "/" + objname 123 if identifier.startswith("./"): 124 identifier = identifier[2:] 125 126 return identifier 127 128 def __load_all(self, dir_name): 129 """ 130 loads all plugins and creates a loaded list of scripts from directory plugins like: 131 [ ( category,[script1, script2,...] ), (category2,[script1, (subcategory,[script1,script2]),...]) ] 132 """ 133 walked = [] 134 135 current = os.path.join(self.base_path, dir_name) 136 if os.path.isdir(current): 137 dir_list = self.__walk_dir_tree(current) 138 walked.append((current, dir_list)) 139 if self.module_registrant: 140 self.module_registrant.end_loading() 141 142 return walked 143 144 def __walk_dir_tree(self, dirname): 145 dir_list = [] 146 147 self.__logger.debug("__walk_dir_tree. START dir=%s", dirname) 148 149 for f in os.listdir(dirname): 150 current = os.path.join(dirname, f) 151 if os.path.isfile(current) and f.endswith("py"): 152 if self.module_registrant: 153 self._load_py_from_file(current) 154 155 dir_list.append(current) 156 elif os.path.isdir(current): 157 ret = self.__walk_dir_tree(current) 158 if ret: 159 dir_list.append((f, ret)) 160 161 return dir_list 162