plugin_manager.py 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import importlib
  2. import inspect
  3. from pathlib import Path
  4. from typing import Dict, List, Type, Optional
  5. import sys
  6. from .plugin_interface import CustomDataProcessorPlugin
  7. class PluginManager:
  8. """Manages the discovery and loading of data processor plugins."""
  9. def __init__(self, plugin_dir: Path):
  10. self.plugin_dir = plugin_dir
  11. self.plugins: Dict[str, Type[CustomDataProcessorPlugin]] = {}
  12. self._load_plugins()
  13. def _load_plugins(self) -> None:
  14. """发现并加载插件目录中的所有插件"""
  15. if not self.plugin_dir.exists():
  16. print(f"未找到插件目录: {self.plugin_dir}")
  17. return
  18. # 将插件目录添加到Python路径
  19. sys.path.insert(0, str(self.plugin_dir.parent))
  20. try:
  21. # 查找插件目录中的Python文件
  22. for plugin_file in self.plugin_dir.glob("*.py"):
  23. if plugin_file.name == "__init__.py":
  24. continue
  25. try:
  26. # 修改模块导入方式,直接使用文件名
  27. module_name = f"plugins.{plugin_file.stem}"
  28. print(f"尝试加载插件模块: {module_name}")
  29. module = importlib.import_module(module_name)
  30. # 在模块中查找插件类
  31. for name, obj in inspect.getmembers(module):
  32. if (inspect.isclass(obj)
  33. and issubclass(obj, CustomDataProcessorPlugin)
  34. and obj != CustomDataProcessorPlugin):
  35. # 从类名中获取关键词(移除DataProcessor或Processor后缀)
  36. keyword = name.lower().replace('dataprocessor', '').replace('processor', '')
  37. self.plugins[keyword] = obj
  38. print(f"成功加载插件: {name}, 关键词: {keyword}")
  39. except ImportError as e:
  40. print(f"导入插件 {plugin_file.name} 失败: {e}")
  41. except Exception as e:
  42. print(f"加载插件 {plugin_file.name} 时出错: {e}")
  43. finally:
  44. # 从Python路径中移除插件目录
  45. if str(self.plugin_dir.parent) in sys.path:
  46. sys.path.remove(str(self.plugin_dir.parent))
  47. def get_plugins(self) -> List[Type[CustomDataProcessorPlugin]]:
  48. """Returns a list of all loaded plugin classes."""
  49. return list(self.plugins.values())
  50. def find_plugin_by_folder_name(self, folder_name: str) -> Optional[Type[CustomDataProcessorPlugin]]:
  51. """根据文件夹名称查找匹配的插件"""
  52. folder_name = folder_name.lower()
  53. for keyword, plugin_class in self.plugins.items():
  54. if keyword in folder_name:
  55. return plugin_class
  56. return None
  57. def get_plugin_for_data(self, zip_path: Path, folder_name: str) -> Type[CustomDataProcessorPlugin]:
  58. """查找能处理给定数据的插件"""
  59. # 首先通过文件夹名称匹配插件
  60. plugin_class = self.find_plugin_by_folder_name(folder_name)
  61. if plugin_class:
  62. try:
  63. plugin = plugin_class()
  64. if plugin.can_handle(zip_path, folder_name):
  65. return plugin_class
  66. except Exception as e:
  67. print(f"检查插件 {plugin_class.__name__} 时出错: {e}")
  68. return None