pbf.controller.PluginsManager
1import os 2import traceback 3 4try: 5 from ..config import plugins_directory, plugins_disabled 6 from ..utils.Logging import Logger 7 from ..utils import Path, MetaData 8 from ..setup import ListenerManager 9 from ..error import NoApiError 10except ImportError: 11 from pbf.config import plugins_directory, plugins_disabled 12 from pbf.utils.Logging import Logger 13 from pbf.utils import Path, MetaData 14 from pbf.setup import ListenerManager 15 from pbf.error import NoApiError 16 17logger = Logger(__name__) 18 19 20class PluginsManager: 21 plugins: dict = {} 22 api: dict = {} 23 plugin_name: str = None 24 25 def __init__(self, path: str = plugins_directory): 26 """ 27 初始化PluginsManager。 28 :param path: str (可选)插件目录,默认为`pbf.config.plugins_directory` 29 :return: None 30 """ 31 self.path = Path.replace(path) 32 33 def clearPlugins(self): 34 """ 35 清空所有插件。 36 :return: None 37 """ 38 # 销毁所有self.plugins中的对象 39 for key, _ in self.plugins.items(): 40 self.disable(key, pop_flag=False) 41 # 清空self.plugins 42 self.plugins.clear() 43 # 销毁Api 44 self.api.clear() 45 ListenerManager.clear() 46 47 def loadPlugins(self, enter: bool = True): 48 """ 49 Load all plugins in the directory. 50 :param enter: bool (可选)是否调用`_enter`函数,默认为`True` 51 :return: None 52 """ 53 self.clearPlugins() 54 for plugin in os.listdir(self.path): 55 if plugin.startswith("__") or plugin.startswith("."): 56 continue 57 if plugin.endswith(".py"): 58 plugin = plugin[:-3] 59 logger.info(f"Loading plugin: `{plugin}`") 60 if plugin in plugins_disabled: 61 logger.warning(f"Plugin `{plugin}` is disabled") 62 continue 63 self.plugin_name = plugin 64 self.loadPlugin(plugin, enter=enter) 65 66 def has(self, plugin: str): 67 """ 68 Check if the plugin exists. 69 :param plugin: str Plugin name 70 :return: bool 71 """ 72 return plugin in self.plugins 73 74 def hasApi(self, plugin: str): 75 """ 76 Check if the plugin has an API. 77 :param plugin: str Plugin name 78 :return: bool 79 """ 80 return plugin in self.api 81 82 def checkDependency(self, plugins: dict): 83 """ 84 Plugins dependencies struct: 85 ``` 86 { 87 "plugin_name": { 88 "upper": 1, 89 "lower": 1 90 } 91 } 92 ``` 93 :param plugins: dict Plugins dependencies 94 :return: bool, str 95 """ 96 for key, value in plugins: 97 upper = value.get("upper") 98 lower = value.get("lower") 99 if self.plugins.get(key) is None: 100 return False, f"Plugin `{key}` not found" 101 meta_data: MetaData = self.plugins.get(key).meta_data 102 if upper is not None: 103 if meta_data.versionCode > upper: 104 return False, f"Plugin `{key}` version is too high" 105 if lower is not None: 106 if meta_data.versionCode < lower: 107 return False, f"Plugin `{key}` version is too low" 108 return True, "All dependencies are met" 109 110 def require(self, plugin: str): 111 """ 112 Require the plugin API. 113 :param plugin: str Plugin name 114 :return: Api Object 115 """ 116 if self.hasApi(plugin): 117 return self.api[plugin] 118 raise NoApiError(f"Plugin `{plugin}` not found or has no API") 119 120 def disable(self, plugin: str, pop_flag: bool=True): 121 """ 122 Disable the plugin. 123 :param plugin: str Plugin name 124 :param pop_flag: bool (可选)是否从`self.api`中删除,默认为`True` 125 :return: None 126 """ 127 if self.has(plugin): 128 try: 129 self.plugins[plugin]._exit() 130 except AttributeError: 131 pass 132 except Exception: 133 logger.warning(f"Plugin `{plugin}` failed to load `_exit` function: {traceback.format_exc()}") 134 if pop_flag: 135 self.plugins.pop(plugin) 136 if self.hasApi(plugin): 137 self.api.pop(plugin) 138 ListenerManager.remove_listeners_by_plugin_name(plugin) 139 logger.info(f"Plugin `{plugin}` disabled") 140 else: 141 logger.warning(f"Plugin `{plugin}` not found") 142 143 def loadPlugin(self, plugin: str, enter: bool = True): 144 """ 145 Load the plugin. 146 :param plugin: str Plugin name 147 :param enter: bool (可选)是否调用`_enter`函数,默认为`True` 148 :return: None 149 """ 150 try: 151 plugin_distance = __import__(f"{plugin}") 152 logger.info(plugin_distance.meta_data) 153 if enter: 154 try: 155 plugin_distance._enter() 156 except AttributeError: 157 pass 158 except Exception: 159 logger.warning(f"Plugin `{plugin}` failed to load `_enter` function: {traceback.format_exc()}") 160 try: 161 self.api[plugin] = plugin_distance.Api 162 except Exception: 163 pass 164 self.plugins[plugin] = plugin_distance 165 logger.info(f"Plugin `{plugin}` loaded") 166 except ImportError: 167 logger.error(f"Plugin `{plugin}` failed to load: {traceback.format_exc()}") 168 except Exception: 169 logger.error(f"Plugin `{plugin}` failed to load: {traceback.format_exc()}") 170 171 def enable(self, plugin: str): 172 """ 173 Enable the plugin. 174 :param plugin: str Plugin name 175 :return: None 176 """ 177 self.loadPlugin(plugin) 178 179 def getAllPlugins(self): 180 """ 181 Get all plugins. 182 :return: dict 183 """ 184 ret_dict: dict = {} 185 for key, value in self.plugins.items(): 186 ret_dict[key] = value.meta_data.toDict() 187 return ret_dict 188 189 190if __name__ == "__main__": 191 PluginsManager()
logger =
<pbf.utils.Logging.Logger object>
class
PluginsManager:
21class PluginsManager: 22 plugins: dict = {} 23 api: dict = {} 24 plugin_name: str = None 25 26 def __init__(self, path: str = plugins_directory): 27 """ 28 初始化PluginsManager。 29 :param path: str (可选)插件目录,默认为`pbf.config.plugins_directory` 30 :return: None 31 """ 32 self.path = Path.replace(path) 33 34 def clearPlugins(self): 35 """ 36 清空所有插件。 37 :return: None 38 """ 39 # 销毁所有self.plugins中的对象 40 for key, _ in self.plugins.items(): 41 self.disable(key, pop_flag=False) 42 # 清空self.plugins 43 self.plugins.clear() 44 # 销毁Api 45 self.api.clear() 46 ListenerManager.clear() 47 48 def loadPlugins(self, enter: bool = True): 49 """ 50 Load all plugins in the directory. 51 :param enter: bool (可选)是否调用`_enter`函数,默认为`True` 52 :return: None 53 """ 54 self.clearPlugins() 55 for plugin in os.listdir(self.path): 56 if plugin.startswith("__") or plugin.startswith("."): 57 continue 58 if plugin.endswith(".py"): 59 plugin = plugin[:-3] 60 logger.info(f"Loading plugin: `{plugin}`") 61 if plugin in plugins_disabled: 62 logger.warning(f"Plugin `{plugin}` is disabled") 63 continue 64 self.plugin_name = plugin 65 self.loadPlugin(plugin, enter=enter) 66 67 def has(self, plugin: str): 68 """ 69 Check if the plugin exists. 70 :param plugin: str Plugin name 71 :return: bool 72 """ 73 return plugin in self.plugins 74 75 def hasApi(self, plugin: str): 76 """ 77 Check if the plugin has an API. 78 :param plugin: str Plugin name 79 :return: bool 80 """ 81 return plugin in self.api 82 83 def checkDependency(self, plugins: dict): 84 """ 85 Plugins dependencies struct: 86 ``` 87 { 88 "plugin_name": { 89 "upper": 1, 90 "lower": 1 91 } 92 } 93 ``` 94 :param plugins: dict Plugins dependencies 95 :return: bool, str 96 """ 97 for key, value in plugins: 98 upper = value.get("upper") 99 lower = value.get("lower") 100 if self.plugins.get(key) is None: 101 return False, f"Plugin `{key}` not found" 102 meta_data: MetaData = self.plugins.get(key).meta_data 103 if upper is not None: 104 if meta_data.versionCode > upper: 105 return False, f"Plugin `{key}` version is too high" 106 if lower is not None: 107 if meta_data.versionCode < lower: 108 return False, f"Plugin `{key}` version is too low" 109 return True, "All dependencies are met" 110 111 def require(self, plugin: str): 112 """ 113 Require the plugin API. 114 :param plugin: str Plugin name 115 :return: Api Object 116 """ 117 if self.hasApi(plugin): 118 return self.api[plugin] 119 raise NoApiError(f"Plugin `{plugin}` not found or has no API") 120 121 def disable(self, plugin: str, pop_flag: bool=True): 122 """ 123 Disable the plugin. 124 :param plugin: str Plugin name 125 :param pop_flag: bool (可选)是否从`self.api`中删除,默认为`True` 126 :return: None 127 """ 128 if self.has(plugin): 129 try: 130 self.plugins[plugin]._exit() 131 except AttributeError: 132 pass 133 except Exception: 134 logger.warning(f"Plugin `{plugin}` failed to load `_exit` function: {traceback.format_exc()}") 135 if pop_flag: 136 self.plugins.pop(plugin) 137 if self.hasApi(plugin): 138 self.api.pop(plugin) 139 ListenerManager.remove_listeners_by_plugin_name(plugin) 140 logger.info(f"Plugin `{plugin}` disabled") 141 else: 142 logger.warning(f"Plugin `{plugin}` not found") 143 144 def loadPlugin(self, plugin: str, enter: bool = True): 145 """ 146 Load the plugin. 147 :param plugin: str Plugin name 148 :param enter: bool (可选)是否调用`_enter`函数,默认为`True` 149 :return: None 150 """ 151 try: 152 plugin_distance = __import__(f"{plugin}") 153 logger.info(plugin_distance.meta_data) 154 if enter: 155 try: 156 plugin_distance._enter() 157 except AttributeError: 158 pass 159 except Exception: 160 logger.warning(f"Plugin `{plugin}` failed to load `_enter` function: {traceback.format_exc()}") 161 try: 162 self.api[plugin] = plugin_distance.Api 163 except Exception: 164 pass 165 self.plugins[plugin] = plugin_distance 166 logger.info(f"Plugin `{plugin}` loaded") 167 except ImportError: 168 logger.error(f"Plugin `{plugin}` failed to load: {traceback.format_exc()}") 169 except Exception: 170 logger.error(f"Plugin `{plugin}` failed to load: {traceback.format_exc()}") 171 172 def enable(self, plugin: str): 173 """ 174 Enable the plugin. 175 :param plugin: str Plugin name 176 :return: None 177 """ 178 self.loadPlugin(plugin) 179 180 def getAllPlugins(self): 181 """ 182 Get all plugins. 183 :return: dict 184 """ 185 ret_dict: dict = {} 186 for key, value in self.plugins.items(): 187 ret_dict[key] = value.meta_data.toDict() 188 return ret_dict
PluginsManager(path: str = '{home}/plugins')
def
clearPlugins(self):
34 def clearPlugins(self): 35 """ 36 清空所有插件。 37 :return: None 38 """ 39 # 销毁所有self.plugins中的对象 40 for key, _ in self.plugins.items(): 41 self.disable(key, pop_flag=False) 42 # 清空self.plugins 43 self.plugins.clear() 44 # 销毁Api 45 self.api.clear() 46 ListenerManager.clear()
清空所有插件。
Returns
None
def
loadPlugins(self, enter: bool = True):
48 def loadPlugins(self, enter: bool = True): 49 """ 50 Load all plugins in the directory. 51 :param enter: bool (可选)是否调用`_enter`函数,默认为`True` 52 :return: None 53 """ 54 self.clearPlugins() 55 for plugin in os.listdir(self.path): 56 if plugin.startswith("__") or plugin.startswith("."): 57 continue 58 if plugin.endswith(".py"): 59 plugin = plugin[:-3] 60 logger.info(f"Loading plugin: `{plugin}`") 61 if plugin in plugins_disabled: 62 logger.warning(f"Plugin `{plugin}` is disabled") 63 continue 64 self.plugin_name = plugin 65 self.loadPlugin(plugin, enter=enter)
Load all plugins in the directory.
Parameters
- enter: bool (可选)是否调用
_enter函数,默认为True
Returns
None
def
has(self, plugin: str):
67 def has(self, plugin: str): 68 """ 69 Check if the plugin exists. 70 :param plugin: str Plugin name 71 :return: bool 72 """ 73 return plugin in self.plugins
Check if the plugin exists.
Parameters
- plugin: str Plugin name
Returns
bool
def
hasApi(self, plugin: str):
75 def hasApi(self, plugin: str): 76 """ 77 Check if the plugin has an API. 78 :param plugin: str Plugin name 79 :return: bool 80 """ 81 return plugin in self.api
Check if the plugin has an API.
Parameters
- plugin: str Plugin name
Returns
bool
def
checkDependency(self, plugins: dict):
83 def checkDependency(self, plugins: dict): 84 """ 85 Plugins dependencies struct: 86 ``` 87 { 88 "plugin_name": { 89 "upper": 1, 90 "lower": 1 91 } 92 } 93 ``` 94 :param plugins: dict Plugins dependencies 95 :return: bool, str 96 """ 97 for key, value in plugins: 98 upper = value.get("upper") 99 lower = value.get("lower") 100 if self.plugins.get(key) is None: 101 return False, f"Plugin `{key}` not found" 102 meta_data: MetaData = self.plugins.get(key).meta_data 103 if upper is not None: 104 if meta_data.versionCode > upper: 105 return False, f"Plugin `{key}` version is too high" 106 if lower is not None: 107 if meta_data.versionCode < lower: 108 return False, f"Plugin `{key}` version is too low" 109 return True, "All dependencies are met"
Plugins dependencies struct:
{
"plugin_name": {
"upper": 1,
"lower": 1
}
}
Parameters
- plugins: dict Plugins dependencies
Returns
bool, str
def
require(self, plugin: str):
111 def require(self, plugin: str): 112 """ 113 Require the plugin API. 114 :param plugin: str Plugin name 115 :return: Api Object 116 """ 117 if self.hasApi(plugin): 118 return self.api[plugin] 119 raise NoApiError(f"Plugin `{plugin}` not found or has no API")
Require the plugin API.
Parameters
- plugin: str Plugin name
Returns
Api Object
def
disable(self, plugin: str, pop_flag: bool = True):
121 def disable(self, plugin: str, pop_flag: bool=True): 122 """ 123 Disable the plugin. 124 :param plugin: str Plugin name 125 :param pop_flag: bool (可选)是否从`self.api`中删除,默认为`True` 126 :return: None 127 """ 128 if self.has(plugin): 129 try: 130 self.plugins[plugin]._exit() 131 except AttributeError: 132 pass 133 except Exception: 134 logger.warning(f"Plugin `{plugin}` failed to load `_exit` function: {traceback.format_exc()}") 135 if pop_flag: 136 self.plugins.pop(plugin) 137 if self.hasApi(plugin): 138 self.api.pop(plugin) 139 ListenerManager.remove_listeners_by_plugin_name(plugin) 140 logger.info(f"Plugin `{plugin}` disabled") 141 else: 142 logger.warning(f"Plugin `{plugin}` not found")
Disable the plugin.
Parameters
- plugin: str Plugin name
- pop_flag: bool (可选)是否从
self.api中删除,默认为True
Returns
None
def
loadPlugin(self, plugin: str, enter: bool = True):
144 def loadPlugin(self, plugin: str, enter: bool = True): 145 """ 146 Load the plugin. 147 :param plugin: str Plugin name 148 :param enter: bool (可选)是否调用`_enter`函数,默认为`True` 149 :return: None 150 """ 151 try: 152 plugin_distance = __import__(f"{plugin}") 153 logger.info(plugin_distance.meta_data) 154 if enter: 155 try: 156 plugin_distance._enter() 157 except AttributeError: 158 pass 159 except Exception: 160 logger.warning(f"Plugin `{plugin}` failed to load `_enter` function: {traceback.format_exc()}") 161 try: 162 self.api[plugin] = plugin_distance.Api 163 except Exception: 164 pass 165 self.plugins[plugin] = plugin_distance 166 logger.info(f"Plugin `{plugin}` loaded") 167 except ImportError: 168 logger.error(f"Plugin `{plugin}` failed to load: {traceback.format_exc()}") 169 except Exception: 170 logger.error(f"Plugin `{plugin}` failed to load: {traceback.format_exc()}")
Load the plugin.
Parameters
- plugin: str Plugin name
- enter: bool (可选)是否调用
_enter函数,默认为True
Returns
None