新增插件Python依赖管理系统,支持自动检查和安装依赖,优化依赖配置和错误处理,更新相关文档和示例代码。

This commit is contained in:
minecraft1024a
2025-08-13 12:32:07 +08:00
parent d6be518a77
commit 97351ce1ae
10 changed files with 730 additions and 36 deletions

View File

@@ -6,6 +6,7 @@ import toml
import json
import shutil
import datetime
from typing import Union
from src.common.logger import get_logger
from src.plugin_system.base.component_types import (
@@ -42,8 +43,8 @@ class PluginBase(ABC):
@property
@abstractmethod
def python_dependencies(self) -> List[PythonDependency]:
return [] # Python包依赖
def python_dependencies(self) -> List[Union[str, PythonDependency]]:
return [] # Python包依赖支持字符串列表或PythonDependency对象列表
@property
@abstractmethod
@@ -87,6 +88,12 @@ class PluginBase(ABC):
self.plugin_description = self.get_manifest_info("description", "")
self.plugin_author = self._get_author_name()
# 标准化Python依赖为PythonDependency对象
normalized_python_deps = self._normalize_python_dependencies(self.python_dependencies)
# 检查Python依赖
self._check_python_dependencies(normalized_python_deps)
# 创建插件信息对象
self.plugin_info = PluginInfo(
name=self.plugin_name,
@@ -98,7 +105,7 @@ class PluginBase(ABC):
is_built_in=False,
config_file=self.config_file_name or "",
dependencies=self.dependencies.copy(),
python_dependencies=self.python_dependencies.copy(),
python_dependencies=normalized_python_deps,
# manifest相关信息
manifest_data=self.manifest_data.copy(),
license=self.get_manifest_info("license", ""),
@@ -564,6 +571,62 @@ class PluginBase(ABC):
return current
def _normalize_python_dependencies(self, dependencies: Any) -> List[PythonDependency]:
"""将依赖列表标准化为PythonDependency对象"""
from packaging.requirements import Requirement
normalized = []
for dep in dependencies:
if isinstance(dep, str):
try:
# 尝试解析为requirement格式 (如 "package>=1.0.0")
req = Requirement(dep)
version_spec = str(req.specifier) if req.specifier else ""
normalized.append(PythonDependency(
package_name=req.name,
version=version_spec,
install_name=dep # 保持原始的安装名称
))
except Exception:
# 如果解析失败,作为简单包名处理
normalized.append(PythonDependency(
package_name=dep,
install_name=dep
))
elif isinstance(dep, PythonDependency):
normalized.append(dep)
else:
logger.warning(f"{self.log_prefix} 未知的依赖格式: {dep}")
return normalized
def _check_python_dependencies(self, dependencies: List[PythonDependency]) -> bool:
"""检查Python依赖并尝试自动安装"""
if not dependencies:
logger.info(f"{self.log_prefix} 无Python依赖需要检查")
return True
try:
# 延迟导入以避免循环依赖
from src.plugin_system.utils.dependency_manager import get_dependency_manager
dependency_manager = get_dependency_manager()
success, errors = dependency_manager.check_and_install_dependencies(dependencies, self.plugin_name)
if success:
logger.info(f"{self.log_prefix} Python依赖检查通过")
return True
else:
logger.error(f"{self.log_prefix} Python依赖检查失败:")
for error in errors:
logger.error(f"{self.log_prefix} - {error}")
return False
except Exception as e:
logger.error(f"{self.log_prefix} Python依赖检查时发生异常: {e}", exc_info=True)
return False
@abstractmethod
def register_plugin(self) -> bool:
"""