commit
3d5761157a
@ -1,7 +1,9 @@
|
||||
import concurrent
|
||||
import concurrent.futures
|
||||
import os
|
||||
import time
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
from typing import List, Any, Dict, Tuple, Optional
|
||||
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
@ -39,8 +41,9 @@ class PluginMonitorHandler(FileSystemEventHandler):
|
||||
self.__last_modified = current_time
|
||||
# 读取插件根目录下的__init__.py文件,读取class XXXX(_PluginBase)的类名
|
||||
try:
|
||||
plugin_dir = event.src_path.split("plugins/")[1].split("/")[0]
|
||||
init_file = settings.ROOT_PATH / "app" / "plugins" / plugin_dir / "__init__.py"
|
||||
# 使用os.path和pathlib处理跨平台的路径问题
|
||||
plugin_dir = event.src_path.split("plugins" + os.sep)[1].split(os.sep)[0]
|
||||
init_file = Path(settings.ROOT_PATH) / "app" / "plugins" / plugin_dir / "__init__.py"
|
||||
with open(init_file, "r", encoding="utf-8") as f:
|
||||
lines = f.readlines()
|
||||
pid = None
|
||||
@ -91,9 +94,14 @@ class PluginManager(metaclass=Singleton):
|
||||
# 扫描插件目录
|
||||
plugin_package = "app.plugins"
|
||||
if pid:
|
||||
plugin_package = f"{plugin_package}.{pid.lower()}"
|
||||
plugins = ModuleHelper.load_with_pre_filter(
|
||||
"app.plugins",
|
||||
filter_func=lambda name, obj:
|
||||
hasattr(obj, 'init_plugin') and hasattr(obj, "plugin_name") and name == pid
|
||||
)
|
||||
else:
|
||||
plugins = ModuleHelper.load(
|
||||
plugin_package,
|
||||
"app.plugins",
|
||||
filter_func=lambda _, obj: hasattr(obj, 'init_plugin') and hasattr(obj, "plugin_name")
|
||||
)
|
||||
# 已安装插件
|
||||
|
@ -40,6 +40,38 @@ class ModuleHelper:
|
||||
|
||||
return submodules
|
||||
|
||||
@classmethod
|
||||
def load_with_pre_filter(cls, package_path, filter_func=lambda name, obj: True):
|
||||
"""
|
||||
导入子模块
|
||||
:param package_path: 父包名
|
||||
:param filter_func: 子模块过滤函数,入参为模块名和模块对象,返回True则导入,否则不导入
|
||||
:return:
|
||||
"""
|
||||
|
||||
submodules: list = []
|
||||
packages = importlib.import_module(package_path)
|
||||
for importer, package_name, _ in pkgutil.iter_modules(packages.__path__):
|
||||
try:
|
||||
if package_name.startswith('_'):
|
||||
continue
|
||||
full_package_name = f'{package_path}.{package_name}'
|
||||
module = importlib.import_module(full_package_name)
|
||||
# 预检查模块中的对象
|
||||
candidates = [(name, obj) for name, obj in module.__dict__.items() if
|
||||
not name.startswith('_') and isinstance(obj, type)]
|
||||
# 确定是否需要重新加载
|
||||
if any(filter_func(name, obj) for name, obj in candidates):
|
||||
importlib.reload(module)
|
||||
# reload后,对象已经发生变更,重新过滤已经重新加载后的模块中的对象
|
||||
for name, obj in module.__dict__.items():
|
||||
if not name.startswith('_') and isinstance(obj, type) and filter_func(name, obj):
|
||||
submodules.append(obj)
|
||||
except Exception as err:
|
||||
logger.debug(f'加载模块 {package_name} 失败:{str(err)} - {traceback.format_exc()}')
|
||||
|
||||
return submodules
|
||||
|
||||
@staticmethod
|
||||
def dynamic_import_all_modules(base_path: Path, package_name: str):
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user